Синхронизация данных между 1С и внешними информационными системами (через механизм Внешние источники данных) — классическая задача для разработчика. Основная сложность заключается в том, что платформа 1С накладывает определенные ограничения на работу с внешними таблицами. В частности, невозможно в рамках одного запроса выполнить прямое соединение (JOIN) таблицы справочника 1С и таблицы внешнего источника данных. Разберем по шагам, как эффективно решить задачу сравнения полей Id_SD и Id и привести данные в соответствие.
Проанализируем самый популярный и надежный способ — получение данных из двух источников по отдельности с их последующим сопоставлением. Поскольку прямое соединение запрещено, мы будем использовать промежуточное хранилище в оперативной памяти — Таблицу Значений.
Рассмотрим алгоритм действий:
Контрагенты.Пример кода для реализации этого подхода:
// 1. Получаем данные из справочника 1С
Запрос1С = Новый Запрос;
Запрос1С.Текст =
"ВЫБРАТЬ
| Контрагенты.Ссылка КАК Ссылка,
| Контрагенты.Id_SD КАК Id_SD
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| НЕ Контрагенты.ПометкаУдаления";
Таблица1С = Запрос1С.Выполнить().Выгрузить();
// 2. Получаем данные из внешнего источника
ЗапросВИД = Новый Запрос;
ЗапросВИД.Текст =
"ВЫБРАТЬ
| ВнешняяТаблица.Id КАК Id
|ИЗ
| ВнешнийИсточникДанных.SD.Таблица.dbo_BlaBla КАК ВнешняяТаблица";
ТаблицаВИД = ЗапросВИД.Выполнить().Выгрузить();
После получения двух таблиц мы можем использовать метод Левого соединения в новом запросе, чтобы найти записи, которые есть в 1С, но отсутствуют в SD, или наоборот. Чтобы это работало быстро, важно передать одну из таблиц как параметр запроса.
Если задача стоит только в том, чтобы найти объекты, которых нет во внешней базе, мы можем использовать условие НЕ В ИЕРАРХИИ или НЕ В СПИСКЕ. Выясним, как это реализовать оптимально.
Выберем все ID из внешнего источника в массив и передадим этот массив в запрос к справочнику 1С. Это позволит сразу получить список «проблемных» контрагентов, у которых Id_SD не находит соответствия в таблице Id.
// Получаем массив всех ID из внешнего источника
СписокID_SD = ТаблицаВИД.ВыгрузитьКолонку("Id");
ЗапросСверки = Новый Запрос;
ЗапросСверки.Текст =
"ВЫБРАТЬ
| Контрагенты.Ссылка,
| Контрагенты.Id_SD
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| НЕ Контрагенты.Id_SD В (&СписокID_SD)";
ЗапросСверки.УстановитьПараметр("СписокID_SD", СписокID_SD);
РезультатСверки = ЗапросСверки.Выполнить().Выбрать();
Важный момент: Если количество записей во внешнем источнике превышает десятки тысяч, передача огромного массива в параметр В (&СписокID_SD) может негативно сказаться на производительности SQL-сервера. В этом случае лучше использовать временные таблицы.
Рассмотрим оригинальный способ, который позволяет найти расхождения без сложных запросов, используя только механизмы коллекций 1С. Этот метод полезен, если вы хотите увидеть полную картину: и те записи, которых нет в 1С, и те, которых нет во внешнем источнике.
ТаблицуЗначений с колонками: ID, Источник, Счетчик.Источник пишем "1С", в поле Счетчик ставим 1).Источник пишем "SD", в поле Счетчик ставим 1).Свернуть("ID", "Счетчик").Проанализируем результат: если после свертки Счетчик равен 2, значит ID присутствует в обеих системах. Если Счетчик равен 1, то запись уникальна для одной из систем и требует внимания.
Выясним, как обойти ограничение на соединение таблиц наиболее элегантным способом. Платформа 1С позволяет связывать разные наборы данных в СКД. Мы можем создать два набора данных типа «Запрос»:
Контрагенты.ВнешнийИсточникДанных.На закладке Связи наборов данных мы указываем условие связи: НаборДанных1.Id_SD = НаборДанных2.Id. СКД сама выполнит необходимые итерации и соединения на уровне программного кода, предоставив вам готовый отчет с сопоставленными данными. Это избавит вас от необходимости вручную писать алгоритмы перебора строк.
При сопоставлении полей Id_SD и Id часто возникают ошибки, связанные с типами данных. Разберем основные причины, по которым визуально одинаковые ID могут не совпадать:
CHAR с фиксированной длиной, которые дополняются пробелами справа. В 1С Id_SD может быть типом String (Varchar). Перед сравнением обязательно используйте функцию СОКРЛП().Id_SD. Это ускорит операцию соединения в разы.Пример создания индекса во временной таблице:
МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
// Загружаем ТЗ во временную таблицу с индексацией
Запрос.Текст =
"ВЫБРАТЬ
| ТЗ_Данные.Id_SD КАК Id_SD
|ПОМЕСТИТЬ ВТ_Данные1С
|ИЗ
| &ТЗ_Данные КАК ТЗ_Данные
|ИНДЕКСИРОВАТЬ ПО
| Id_SD";
Запрос.УстановитьПараметр("ТЗ_Данные", Таблица1С);
Запрос.Выполнить();
Подводя итог, выбор метода зависит от объема данных. Для небольших таблиц достаточно метода В СПИСКЕ или свертки ТЗ. Для высоконагруженных систем с миллионами записей лучшим решением станет использование СКД или предварительная индексация временных таблиц в пакетном запросе.