При работе с механизмом Внешних источников данных (ВИД) программисты 1С часто сталкиваются с фундаментальным ограничением платформы: невозможно в одном объекте Запрос одновременно обратиться к таблице из стандартных метаданных (справочники, документы, регистры) и к таблице внешнего источника. При попытке такого объединения система выдает ошибку: «Получение данных из нескольких источников данных недопустимо». Это происходит потому, что данные физически находятся в разных базах данных (разных СУБД), и платформа не может выполнить распределенный запрос автоматически.
В данной статье мы разберем эффективные стратегии обхода этого ограничения, рассмотрим программные методы соединения таблиц и выясним, как бороться со специфическими ошибками кодировки SQL (Collation).
Если нам нужно отобрать из внешнего источника только те записи, которые соответствуют нашему набору данных из 1С (например, ТаблицеЗначений), самым оптимальным путем будет предварительное получение уникальных идентификаторов. Проанализируем этот алгоритм по шагам:
ВнешнемуИсточникуДанных.Рассмотрим пример кода, реализующий этот подход:
// 1. Получаем данные из справочника 1С
Запрос1С = Новый Запрос;
Запрос1С.Текст = "ВЫБРАТЬ Ссылка, КодВнешний ИЗ Справочник.Контрагенты ГДЕ ЭтоГруппа = ЛОЖЬ";
ТЗ_1С = Запрос1С.Выполнить().Выгрузить();
// 2. Подготавливаем массив ключей для фильтрации внешнего источника
МассивКлючей = ТЗ_1С.ВыгрузитьКолонку("КодВнешний");
// 3. Делаем отдельный запрос к ВИД
ЗапросВИД = Новый Запрос;
ЗапросВИД.Текст =
"ВЫБРАТЬ
| ВнешняяТаблица.ID,
| ВнешняяТаблица.Наименование,
| ВнешняяТаблица.Остаток
|ИЗ
| ВнешнийИсточникДанных.НашИсточник.Таблицы.dbo_Data КАК ВнешняяТаблица
|ГДЕ
| ВнешняяТаблица.ID В (&МассивКлючей)";
ЗапросВИД.УстановитьПараметр("МассивКлючей", МассивКлючей);
ТЗ_ВИД = ЗапросВИД.Выполнить().Выгрузить();
Важный нюанс: Перед передачей массива в параметр запроса к ВИД, рекомендуется свернуть массив (удалить дубликаты), чтобы уменьшить размер передаваемого SQL-пакета и ускорить работу индекса на стороне внешней СУБД.
СКД — это мощный инструмент, который умеет обходить ограничение на «разные источники» на уровне своей внутренней логики. Мы можем создать два разных Набора данных в одной схеме компоновки:
Связав эти наборы на закладке «Связи наборов данных», мы заставим платформу выполнить соединение за нас. Выясним преимущество этого метода: платформа автоматически сформирует серию подзапросов к внешнему источнику, подставляя значения из первого набора в условия фильтрации. Это избавляет разработчика от написания циклов обхода и ручного слияния таблиц.
Если нам необходимо выполнить сложное соединение (например, ЛЕВОЕ СОЕДИНЕНИЕ), группировку или расчеты над двумя таблицами (из 1С и из ВИД), мы можем использовать Менеджер временных таблиц. Однако здесь есть тонкость: мы не можем поместить таблицу 1С и таблицу ВИД в один менеджер в рамках одного запроса, если этот запрос обращается к физическим таблицам базы.
Правильный алгоритм действий:
ТаблицуЗначений.ТаблицуЗначений.Посмотрим на пример реализации «чистого» запроса-слияния:
МенеджерВТ = Новый МенеджерВременных Таблиц;
ЗапросСлияния = Новый Запрос;
ЗапросСлияния.МенеджерВременныхТаблиц = МенеджерВТ;
// Передаем ТЗ как внешние данные
ЗапросСлияния.УстановитьПараметр("ТЗ_Из_1С", ТЗ_1С);
ЗапросСлияния.УстановитьПараметр("ТЗ_Из_ВИД", ТЗ_ВИД);
ЗапросСлияния.Текст =
"ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_1С ИЗ &ТЗ_Из_1С КАК ТЗ_Из_1С;
|ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_ВИД ИЗ &ТЗ_Из_ВИД КАК ТЗ_Из_ВИД;
|
|ВЫБРАТЬ
| ВТ_1С.Ссылка,
| ВТ_ВИД.Остаток
|ИЗ
| ВТ_1С КАК ВТ_1С
|ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ВИД КАК ВТ_ВИД
|ПО ВТ_1С.КодВнешний = ВТ_ВИД.ID";
Результат = ЗапросСлияния.Выполнить().Выгрузить();
Этот метод позволяет использовать всю мощь языка запросов 1С для сопоставления данных, не нарушая ограничений по источникам.
Проанализируем ситуацию, когда при выполнении запроса к ВИД возникает ошибка: Cannot resolve the collation conflict between "Slovak_CI_AS" and "SQL_Latin1_General_CP1_CS_AS". Это происходит, когда строковые поля во внешней базе имеют кодировку, отличную от кодировки базы данных 1С (обычно это Cyrillic_General_CI_AS).
Если ошибка возникает при использовании оператора ГДЕ Поле В (&Массив), это означает, что SQL Server не может сравнить строку из внешней таблицы со строкой, пришедшей из 1С, из-за разных правил сортировки и сравнения.
Варианты решения:
COLLATE. Например: SELECT Column1 COLLATE Cyrillic_General_CI_AS AS Column1 FROM Table1. Затем в 1С вы подключаете это View как таблицу ВИД.ТаблицеЗначений методом Найти() или НайтиСтроки() в цикле.ADODB.Connection можно отправить «чистый» SQL-запрос непосредственно к серверу СУБД, в тексте которого прописать приведение типов COLLATE вручную.Работа с внешними источниками всегда несет риски производительности. Рассмотрим основные правила:
ГДЕ Поле В (&Массив) превратится в полное сканирование таблицы, что крайне медленно при больших объемах.ТаблицуЗначений «на всякий случай». Всегда ограничивайте выборку максимально узким фильтром по дате, списку ID или другим признакам.Таким образом, несмотря на жесткие ограничения платформы 1С по работе с разнородными источниками данных, сочетание механизмов временных таблиц, СКД и правильной подготовки данных на стороне СУБД позволяет решать задачи интеграции эффективно и быстро.