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

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

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

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

Причина возникновения ошибки

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

Способ 1. Использование временных таблиц и двухэтапного запроса

Это самый распространенный и надежный метод для использования в программном коде. Суть его заключается в том, чтобы сначала получить данные из внешнего источника, сохранить их в промежуточную структуру (Таблицу Значений), а затем передать эту таблицу во второй запрос к основной базе.

Разберем этот процесс по шагам:

  1. Получение данных из внешнего источника. Мы создаем первый запрос, который обращается исключительно к внешним таблицам.
  2. Выгрузка в Таблицу Значений. Результат первого запроса сохраняется в переменную типа ТаблицаЗначений.
  3. Подготовка второго запроса. Мы передаем полученную таблицу в качестве параметра во второй запрос.
  4. Создание временной таблицы. Во втором запросе мы помещаем данные из параметра во временную таблицу и соединяем ее со справочником Номенклатура.

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


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

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

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

Результат = ЗапросОсновной.Выполнить().Выбрать();

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


|ПОМЕСТИТЬ ВТ_ВнешниеДанные
|ИЗ
|	&ВнешниеДанные КАК ВнешниеДанные
|ИНДЕКСИРОВАТЬ ПО
|	ВнешнийКод
|;

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

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

Проанализируем алгоритм настройки СКД:

  1. Создайте первый Набор данных - запрос. В нем выберите данные из внешнего источника. Назовем его НаборДанныхВнешний.
  2. Создайте второй Набор данных - запрос. В нем выберите данные из справочника Номенклатура. Назовем его НаборДанных1С.
  3. Перейдите на вкладку "Связи наборов данных". Это ключевой этап. Здесь вы указываете, что НаборДанныхВнешний является источником связи, а НаборДанных1С — приемником.
  4. Настройте условие связи. Укажите поля, по которым будет происходить сопоставление (например, ВнешнийКод и Код).

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

Тонкости типизации и сопоставления данных

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

Использование Менеджера временных таблиц

Рассмотрим более продвинутый вариант управления памятью. Если вам нужно выполнять несколько последовательных запросов к внешним и внутренним данным, удобно использовать МенеджерВременныхТаблиц. Это позволяет один раз поместить внешние данные в "темп" (временное хранилище на сервере 1С) и обращаться к ним многократно в рамках одного сеанса.


МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос1 = Новый Запрос("ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Данные ИЗ &ТЗ КАК ТЗ");
Запрос1.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос1.УстановитьПараметр("ТЗ", ВнешняяТЗ);
Запрос1.Выполнить();

// Теперь ВТ_Данные доступна в любом другом запросе, использующем этот МенеджерВТ
Запрос2 = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура ГДЕ Код В (ВЫБРАТЬ Код ИЗ ВТ_Данные)");
Запрос2.МенеджерВременныхТаблиц = МенеджерВТ;
Результат = Запрос2.Выполнить();

Подведение итогов

Мы выяснили, что прямое соединение внешнего источника и справочника 1С в одном запросе невозможно из-за архитектурных ограничений платформы. Для решения задачи мы всегда должны разделять процесс на два этапа: извлечение данных во временное хранилище (Таблица Значений или Набор данных СКД) и последующее соединение с объектами метаданных 1С. Соблюдение правил индексации и приведение типов данных — залог быстрого и корректного результата.

← На главную