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

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

При интеграции 1С со сторонними базами данных (Oracle, MS SQL, PostgreSQL) разработчики часто сталкиваются с необходимостью сопоставить данные из внешнего источника с объектами текущей информационной базы (например, получить ссылки справочников 1С по внешним кодам или идентификаторам). Стандартный подход с выгрузкой результата запроса внешнего источника в ТаблицаЗначений с последующей передачей во второй запрос в виде временной таблицы создает избыточную нагрузку на оперативную память сервера, особенно при больших объемах данных. Разберем, как устроен этот механизм, выясним причины ограничений платформы и рассмотрим оптимальные способы стыковки разнородных данных.

Почему 1С не позволяет объединить внешний источник и таблицы базы в одном запросе?

Платформа 1С принципиально разделяет контексты выполнения запросов. Выясним, почему стандартный язык запросов 1С выдает ошибку "Получение данных из нескольких источников данных недопустимо" при попытке соединения:

  1. Разные физические СУБД: Запрос к таблицам 1С транслируется и исполняется на сервере базы данных 1С, а запрос к таблицам внешнего источника данных (ВИД) передается через драйвер (ODBC / OLE DB) напрямую во внешнюю СУБД. Транслятор запросов 1С не выполняет распределенные межсерверные запросы (heterogeneous queries) в рамках одной инструкции.
  2. Ограничение временных таблиц внешнего источника: Конструкция вида ВнешнийИсточникДанных.<ИмяИсточника>.ВременнаяТаблица.<ИмяВТ> предназначена исключительно для промежуточных вычислений внутри самой внешней СУБД в рамках единого пакета запросов к этому внешнему источнику. Получить доступ к такой временной таблице из запроса к основной базе 1С технически невозможно.

Способ 1. Использование нескольких наборов данных в СКД (Схеме компоновки данных)

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

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

  1. Создание первого набора данных: Добавляем Набор данных - запрос к таблицам 1С (например, к справочнику Номенклатура), выбираем необходимые поля (Ссылка, Код, Артикул).
  2. Создание второго набора данных: Добавляем второй Набор данных - запрос, указав в качестве источника данных внешний источник. В тексте запроса выбираем таблицы внешнего источника (например, цены, остатки или штрихкоды из базы Oracle).
  3. Настройка связей наборов данных: Переходим на вкладку Связи наборов данных. Указываем источник связи (первый набор), приемник связи (второй набор) и поля соединения (например, Код).
  4. Оптимизация передачи параметров: В колонке Параметры связи наборов обязательно указываем имя параметра фильтрации. В этом случае СКД автоматически добавит условие во внешний запрос, выбирая только те записи, которые реально присутствуют в выборке первого набора, вместо полной выборки всей внешней таблицы.

Если соединенные данные нужны не для отображения в отчете, а для программной обработки в коде (например, для регламентной синхронизации), выполним схему компоновки программно с выводом в коллекцию значений:


// Создаем схему и настройки компоновки
СхемаКомпоновкиДанных = ПолучитьМакет("СхемаСтыковкиДанных");
Настройки = СхемаКомпоновкиДанных.НастройкиПоУмолчанию;

// Инициализируем компоновщик макета
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки,,, Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));

// Выполняем компоновку данных
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);

// Выводим результат напрямую в ТаблицуЗначений без построения отчета
ТаблицаРезультат = Новый ТаблицаЗначений;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(ТаблицаРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);

Способ 2. Прямая привязка ссылочных типов 1С в конфигураторе

Рассмотрим встроенный механизм метаданных внешних источников. Если во внешней таблице хранится идентификатор объекта 1С (код, артикул или строковое представление УИД), платформа позволяет настроить связь без использования сложных конструкций:

  1. Открываем свойства таблицы внешнего источника данных в конфигураторе.
  2. Находим поле, содержащее идентификатор объекта.
  3. В свойстве Тип для этого поля выбираем не примитивный тип, а ссылочный тип конфигурации (например, СправочникСсылка.Номенклатура или СправочникСсылка.Контрагенты).
  4. После этого в обычных запросах к таблице внешнего источника данных через точку можно обращаться к реквизитам связанного справочника 1С, а платформа самостоятельно выполнит сопоставление по значению ключа.

Способ 3. Создание представлений (View) на уровне СУБД

Проанализируем архитектурное решение для высоконагруженных систем. Если требуется максимальная скорость выборки без перекладывания нагрузки на сервер 1С, соединение баз можно вынести на уровень самих СУБД:

  1. Настройка межсерверной связи: В СУБД настраивается механизм федеративных связей — Database Link в Oracle, Linked Server в MS SQL Server или postgres_fdw (Foreign Data Wrapper) в PostgreSQL.
  2. Создание представления: На стороне внешней СУБД создается представление (VIEW), которое нативно соединяет локальные таблицы с таблицами информационной базы 1С по ключевым полям.
  3. Подключение в 1С: Полученное представление добавляется в ветку Внешние источники данных как единая таблица. В коде 1С выполняется простой одиночный запрос к этой таблице, получающий уже полностью сопоставленный результат.

Способ 4. Пакетная выгрузка порциями (пагинация)

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


// Задаем размер пакета для снижения нагрузки на память
РазмерПакета = 5000;
ПоследнийИД = 0;

Пока Истина Цикл
    ЗапросВИД = Новый Запрос;
    ЗапросВИД.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ " + Строка(РазмерПакета) + "
        |	ВнешняяТаблица.ID КАК ID,
        |	ВнешняяТаблица.КодОбъекта КАК КодОбъекта,
        |	ВнешняяТаблица.Количество КАК Количество
        |ИЗ
        |	ВнешнийИсточникДанных.ВнешняяБаза.Таблица.Данные КАК ВнешняяТаблица
        |ГДЕ
        |	ВнешняяТаблица.ID > &ПоследнийИД
        |УПОРЯДОЧИТЬ ПО
        |	ID";
    ЗапросВИД.УстановитьПараметр("ПоследнийИД", ПоследнийИД);
    
    Выборка = ЗапросВИД.Выполнить().Выбрать();
    Если Выборка.Количество() = 0 Тогда
        Прервать;
    КонецЕсли;
    
    Пока Выборка.Следующий() Цикл
        ПоследнийИД = Выборка.ID;
        // Выполняем точечный поиск или запись в базу 1С
        Ссылка1С = Справочники.Номенклатура.НайтиПоКоду(Выборка.КодОбъекта);
        // Обработка полученных данных
    КонецЦикла;
КонецЦикла;

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

← На главную