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

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

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

В данной статье мы разберем эффективные стратегии обхода этого ограничения, рассмотрим программные методы соединения таблиц и выясним, как бороться со специфическими ошибками кодировки SQL (Collation).

Способ 1. Фильтрация внешнего источника по массиву ключей

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

  1. Выгружаем необходимые ключевые поля из справочника или результата запроса в массив.
  2. Передаем этот массив в качестве параметра в отдельный запрос к ВнешнемуИсточникуДанных.
  3. Получаем результат и соединяем две таблицы программно.

Рассмотрим пример кода, реализующий этот подход:


// 1. Получаем данные из справочника 1С
Запрос1С = Новый Запрос;
Запрос1С.Текст = "ВЫБРАТЬ Ссылка, КодВнешний ИЗ Справочник.Контрагенты ГДЕ ЭтоГруппа = ЛОЖЬ";
ТЗ_1С = Запрос1С.Выполнить().Выгрузить();

// 2. Подготавливаем массив ключей для фильтрации внешнего источника
МассивКлючей = ТЗ_1С.ВыгрузитьКолонку("КодВнешний");

// 3. Делаем отдельный запрос к ВИД
ЗапросВИД = Новый Запрос;
ЗапросВИД.Текст = 
    "ВЫБРАТЬ
    |   ВнешняяТаблица.ID,
    |   ВнешняяТаблица.Наименование,
    |   ВнешняяТаблица.Остаток
    |ИЗ
    |   ВнешнийИсточникДанных.НашИсточник.Таблицы.dbo_Data КАК ВнешняяТаблица
    |ГДЕ
    |   ВнешняяТаблица.ID В (&МассивКлючей)";

ЗапросВИД.УстановитьПараметр("МассивКлючей", МассивКлючей);
ТЗ_ВИД = ЗапросВИД.Выполнить().Выгрузить();

Важный нюанс: Перед передачей массива в параметр запроса к ВИД, рекомендуется свернуть массив (удалить дубликаты), чтобы уменьшить размер передаваемого SQL-пакета и ускорить работу индекса на стороне внешней СУБД.

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

СКД — это мощный инструмент, который умеет обходить ограничение на «разные источники» на уровне своей внутренней логики. Мы можем создать два разных Набора данных в одной схеме компоновки:

  1. Набор данных - запрос: Обращается к стандартным таблицам 1С.
  2. Набор данных - запрос (или объект): Обращается к таблицам ВИД.

Связав эти наборы на закладке «Связи наборов данных», мы заставим платформу выполнить соединение за нас. Выясним преимущество этого метода: платформа автоматически сформирует серию подзапросов к внешнему источнику, подставляя значения из первого набора в условия фильтрации. Это избавляет разработчика от написания циклов обхода и ручного слияния таблиц.

Способ 3. Соединение во временных таблицах

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

Правильный алгоритм действий:

  1. Выполнить запрос к 1С, выгрузить результат в ТаблицуЗначений.
  2. Выполнить запрос к ВИД, выгрузить результат во вторую ТаблицуЗначений.
  3. Создать третий запрос, в который передать обе таблицы как внешние наборы данных.

Посмотрим на пример реализации «чистого» запроса-слияния:


МенеджерВТ = Новый МенеджерВременных Таблиц;
ЗапросСлияния = Новый Запрос;
ЗапросСлияния.МенеджерВременныхТаблиц = МенеджерВТ;

// Передаем ТЗ как внешние данные
ЗапросСлияния.УстановитьПараметр("ТЗ_Из_1С", ТЗ_1С);
ЗапросСлияния.УстановитьПараметр("ТЗ_Из_ВИД", ТЗ_ВИД);

ЗапросСлияния.Текст = 
    "ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_1С ИЗ &ТЗ_Из_1С КАК ТЗ_Из_1С;
    |ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_ВИД ИЗ &ТЗ_Из_ВИД КАК ТЗ_Из_ВИД;
    |
    |ВЫБРАТЬ
    |   ВТ_1С.Ссылка,
    |   ВТ_ВИД.Остаток
    |ИЗ
    |   ВТ_1С КАК ВТ_1С
    |ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ВИД КАК ВТ_ВИД
    |ПО ВТ_1С.КодВнешний = ВТ_ВИД.ID";

Результат = ЗапросСлияния.Выполнить().Выгрузить();

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

Решение проблемы конфликта кодировок (Collation)

Проанализируем ситуацию, когда при выполнении запроса к ВИД возникает ошибка: Cannot resolve the collation conflict between "Slovak_CI_AS" and "SQL_Latin1_General_CP1_CS_AS". Это происходит, когда строковые поля во внешней базе имеют кодировку, отличную от кодировки базы данных 1С (обычно это Cyrillic_General_CI_AS).

Если ошибка возникает при использовании оператора ГДЕ Поле В (&Массив), это означает, что SQL Server не может сравнить строку из внешней таблицы со строкой, пришедшей из 1С, из-за разных правил сортировки и сравнения.

Варианты решения:

Практические советы по оптимизации

Работа с внешними источниками всегда несет риски производительности. Рассмотрим основные правила:

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

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

← На главную