Как объединить данные информационной базы 1С и внешнего источника данных в одном запросе?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции систем часто возникает задача соединить данные из информационной базы 1С (например, справочник или регистр сведений) с таблицей из внешнего источника данных (ВИД). На первый взгляд кажется логичным написать классический запрос с оператором ЛЕВОЕ СОЕДИНЕНИЕ, полагаясь на наличие индексов. Однако при попытке выполнить такой запрос платформа выдает исключение: «Получение данных из нескольких источников данных недопустимо!».

Разберем архитектурные причины этого поведения платформы, выясним, как работают временные таблицы во внешних источниках, и рассмотрим проверенные способы решения поставленной задачи.

Почему 1С запрещает соединение в одном запросе

Проанализируем архитектуру механизма запросов платформы «1С:Предприятие». Когда мы выполняем запрос к базе данных, платформа не выполняет соединения таблиц собственными силами в оперативной памяти сервера приложений. Вместо этого встроенный транслятор преобразует текст запроса 1С в нативный диалект SQL той СУБД, на которой развернута информационная база (MS SQL Server, PostgreSQL, Oracle и т.д.), и отправляет его на исполнение целиком на сторону сервера баз данных.

В платформе 1С отсутствует распределенный (федеративный) SQL-движок. Каждый объект Запрос строго привязан к одному контексту: либо к рабочей информационной базе, либо к конкретному внешнему источнику данных. СУБД информационной базы 1С ничего не знает о таблицах сторонней базы, и наоборот. По этой причине прямое объединение или соединение таблиц из разных источников внутри одного текста запроса синтаксически заблокировано разработчиками платформы.

Особенности использования временных таблиц в ВИД

Иногда возникает идея обойти ограничение через создание временных таблиц: поместить данные из ВИД во временную таблицу и затем связать ее с таблицей 1С. Рассмотрим, как на самом деле работает этот механизм начиная с версии платформы 8.3:

  1. Платформа действительно поддерживает временные таблицы во внешних источниках, но требует строгого указания полного пути к объекту: ПОМЕСТИТЬ ВнешнийИсточникДанных.<ИмяИсточника>.ВременнаяТаблица.<ИмяТаблицы>.
  2. Если не указать имя источника полностью, платформа попытается создать временную таблицу в контексте информационной базы 1С, что мгновенно вызовет ошибку нескольких источников данных.
  3. Физически такая временная таблица создается во внешней СУБД (например, в системной базе tempdb для MS SQL Server). Следовательно, соединить ее с таблицами основной базы 1С все равно невозможно, так как они физически размещены в разных базах или даже на разных серверах.

Способ 1. Соединение наборов данных в СКД

Самым простым и штатным способом объединить данные двух баз на уровне платформы является Система компоновки данных. СКД умеет работать с несколькими источниками и выполняет соединение наборов данных силами собственного процессора компоновки.

Разберем по шагам правильную настройку схемы компоновки данных:

  1. Создаем первый набор данных — запрос к объектам информационной базы 1С (например, выбираем номенклатуру и ее артикулы).
  2. Создаем второй набор данных — запрос к внешнему источнику данных. В этом запросе обязательно указываем отбор по параметру: ГДЕ Ключ В (&МассивКлючей).
  3. Переходим на вкладку «Связи наборов данных». Указываем источник связи (набор 1С), приемник (набор ВИД) и поля связи.
  4. В колонке «Параметры» обязательно настраиваем передачу поля связи из первого набора в параметр МассивКлючей второго набора.

Важный нюанс производительности: если не настроить передачу параметра в связях наборов, СКД выполнит запрос ко второму набору без фильтрации. В этом случае во временную память сервера 1С будет выгружена вся внешняя таблица целиком. Настройка передачи массива ключей заставляет платформу считывать данные из внешнего источника небольшими порциями, задействуя индекс по ключевому полю на стороне внешней СУБД.

Способ 2. Выборка в Таблицу Значений с последующей передачей в 1С

Если результат требуется получить программно в модуле, стандартным подходом является разделение задачи на два последовательных запроса с промежуточной передачей данных через объект ТаблицаЗначений.

Посмотрим на пример реализации данного алгоритма:


// Шаг 1. Получаем необходимые данные из внешнего источника данных
ЗапросВИД = Новый Запрос;
ЗапросВИД.Текст = 
    "ВЫБРАТЬ
    |	ВнешняяТаблица.КодТовара КАК КодТовара,
    |	ВнешняяТаблица.ОстатокНаСкладе КАК ОстатокНаСкладе
    |ИЗ
    |	ВнешнийИсточникДанных.ВнешняяБаза.Таблица.Остатки КАК ВнешняяТаблица
    |ГДЕ
    |	ВнешняяТаблица.Актуален = ИСТИНА";

ТЗ_ВнешниеДанные = ЗапросВИД.Выполнить().Выгрузить();

// Шаг 2. Передаем полученную таблицу в запрос к базе 1С
Запрос1С = Новый Запрос;
Запрос1С.Текст = 
    "ВЫБРАТЬ
    |	ТЗ.КодТовара КАК КодТовара,
    |	ТЗ.ОстатокНаСкладе КАК ОстатокНаСкладе
    |ПОМЕСТИТЬ ВТ_ВнешниеДанные
    |ИЗ
    |	&ТЗДанные КАК ТЗ
    |ИНДЕКСИРОВАТЬ ПО
    |	КодТовара
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |	Номенклатура.Ссылка КАК Номенклатура,
    |	Номенклатура.Артикул КАК Артикул,
    |	ЕСТЬNULL(ВТ_ВнешниеДанные.ОстатокНаСкладе, 0) КАК ВнешнийОстаток
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |		ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ВнешниеДанные КАК ВТ_ВнешниеДанные
    |		ПО Номенклатура.Артикул = ВТ_ВнешниеДанные.КодТовара
    |ГДЕ
    |	НЕ Номенклатура.ЭтоГруппа";

Запрос1С.УстановитьПараметр("ТЗДанные", ТЗ_ВнешниеДанные);
Результат = Запрос1С.Выполнить().Выгрузить();

Обратите внимание на директиву ИНДЕКСИРОВАТЬ ПО при помещении таблицы значений во временную таблицу. Это гарантирует быстрое соединение с основной таблицей базы 1С.

Стоит учитывать, что обратная операция невозможна: передать ТаблицуЗначений платформы 1С в качестве параметра во внешний источник данных нельзя, так как сторонние СУБД не поддерживают внутреннюю сериализацию коллекций значений 1С.

Способ 3. Интеграция на уровне СУБД (Linked Server / FDW)

Когда объемы соединяемых данных достигают сотен тысяч или миллионов строк, перегонять их через оперативную память сервера «1С:Предприятия» становится неэффективно. В таких сценариях интеграцию переносят на уровень СУБД:

  1. На стороне внешней СУБД настраивается связь с базой данных 1С с помощью встроенных механизмов (например, Linked Server в MS SQL Server или postgres_fdw в PostgreSQL).
  2. Создается SQL-представление (VIEW), которое нативно объединяет внешние таблицы и таблицы базы 1С с использованием физических индексов обеих сторон.
  3. Созданное представление подключается в конфигурации 1С как таблица внешнего источника данных.

В этом случае платформа 1С выполняет обычный запрос к одному источнику, а всю тяжелую работу по оптимизации и соединению выполняет внешний сервер СУБД.

← На главную