Как сравнить две таблицы значений, полученные из разных баз через COM-соединение

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

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

Выясним причину ошибки «Неверный параметр»

Рассмотрим, что происходит, когда мы запрашиваем данные из внешней базы через COM-соединение. Если мы выбираем поле Ссылка внешнего справочника и помещаем его в локальную таблицу значений, то в колонке оказывается не локальная ссылка 1С, а объект типа COMОбъект (внешняя ссылка).

Механизм временных таблиц языка запросов 1С не умеет работать со сторонними COM-объектами. При попытке передать такую таблицу значений в качестве параметра запроса Запрос.УстановитьПараметр("ТЗ", ТаблицаЗначений) платформа выдает ошибку «Неверный параметр» по двум основным причинам:

  1. Недопустимый тип данных в колонке: через COM-соединение можно передавать только примитивные типы данных (число, строка, дата, булево). Ссылка на объект внешней базы является COM-объектом и не может обрабатываться СУБД текущей базы.
  2. Отсутствие типизации колонок: для передачи таблицы значений во временную таблицу запроса каждая колонка должна иметь явно заданный тип (ОписательТипов). Если колонка создана динамически без указания типа, запрос не сможет сформировать структурированную временную таблицу.

Способ 1. Приведение УИД к примитивному типу (Строка 36)

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

Посмотрим на алгоритм реализации по шагам:

  1. Создаем локальную таблицу значений с явным указанием типов колонок.
  2. Заполняем таблицу значений строковыми представлениями УИД (строка из 36 символов) и другими необходимыми реквизитами (артикул, наименование).
  3. Передаем сформированные таблицы в параметр запроса и выполняем соединение во временных таблицах.

Проанализируем пример кода для подготовки локальной таблицы значений:


// Создаем таблицу значений с явным описанием типов
ТЗ_База1 = Новый ТаблицаЗначений;
МассивТиповСтрока = Новый Массив;
МассивТиповСтрока.Добавить(Тип("Строка"));
КвалификаторыСтроки = Новый КвалификаторыСтроки(36);
ОписаниеТипаУИД = Новый ОписаниеТипов(МассивТиповСтрока, , КвалификаторыСтроки);

ТЗ_База1.Колонки.Добавить("УИД", ОписаниеТипаУИД);
ТЗ_База1.Колонки.Добавить("Наименование", Новый ОписаниеТипов("Строка"));

// Заполняем ТЗ из COM-соединения
ВыборкаCOM = ЗапросCOM.Выполнить().Выбрать();
Пока ВыборкаCOM.Следующий() Цикл
    НоваяСтрока = ТЗ_База1.Добавить();
    // Преобразуем уникальный идентификатор COM-объекта в строку
    НоваяСтрока.УИД = Строка(ВыборкаCOM.УИД); 
    НоваяСтрока.Наименование = ВыборкаCOM.Наименование;
КонецЦикла;

После того как данные из обоих источников собраны в таблицы значений с примитивными типами, объединим их с помощью локального запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ТЗ1.УИД КАК УИД,
    |	ТЗ1.Наименование КАК Наименование_База1,
    |	ТЗ2.Наименование КАК Наименование_База2
    |ПОМЕСТИТЬ ВТ_База1
    |ИЗ
    |	&ТЗ_База1 КАК ТЗ1
    |;
    |
    |ВЫБРАТЬ
    |	ТЗ2.УИД КАК УИД
    |ПОМЕСТИТЬ ВТ_База2
    |ИЗ
    |	&ТЗ_База2 КАК ТЗ2
    |;
    |
    |ВЫБРАТЬ
    |	ВТ_База1.УИД КАК УИД,
    |	ВТ_База1.Наименование_База1 КАК Наименование
    |ИЗ
    |	ВТ_База1 КАК ВТ_База1
    |		ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_База2 КАК ВТ_База2
    |		ПО ВТ_База1.УИД = ВТ_База2.УИД";

Запрос.УстановитьПараметр("ТЗ_База1", ТЗ_База1);
Запрос.УстановитьПараметр("ТЗ_База2", ТЗ_База2);

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

Способ 2. Выполнение поиска прямо на стороне внешних баз

Если сопоставление требуется выполняться последовательно (например, поиск элементов из Базы 1 в Базе 2 по ключевым реквизитам), рассмотрим вариант выполнения запросов непосредственно через COM-объект внешней базы.

В этом случае мы формируем объект Запрос внутри COM-соединения и передаем туда примитивные параметры (ИНН, КПП, Артикул или Код). Посмотрим на пример функции проверки наличия элемента во внешней базе:


Функция НайтиНоменклатуруВоВнешнейБазе(СоединениеCOM, Артикул)
    
    OLEЗапрос = СоединениеCOM.NewObject("Запрос");
    OLEЗапрос.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ 1
        |	Номенклатура.Ссылка КАК Ссылка
        |ИЗ
        |	Справочник.Номенклатура КАК Номенклатура
        |ГДЕ
        |	Номенклатура.Артикул = &Артикул";
        
    OLEЗапрос.УстановитьПараметр("Артикул", Артикул);
    Выборка = OLEЗапрос.Выполнить().Выбрать();
    
    Если Выборка.Следующий() Тогда
        Возврат Истина; // Элемент найден
    Иначе
        Возврат Ложь; // Элемент отсутствует
    КонецЕсли;
    
КонецФункции

Способ 3. Использование конфигурации «Конвертация данных 2.0»

Если задача заключается в переносе и синхронизации номенклатуры между несколькими базами с поиском дублей и перенесением остатков, использование прямых COM-запросов и ручное «схлопывание» таблиц становится трудоемким процессом.

Разберем, почему в сложных сценариях переноса рекомендуется переходить на типовой механизм Конвертации данных (КД 2.0):

Резюме

Для устранения ошибки «Неверный параметр» при работе с таблицами значений из COM-источников соблюдаем простые правила:

  1. Передаем в таблицы значений только примитивные типы данных (Строка, Число, Дата, Булево).
  2. При получении ссылок из внешней базы всегда преобразуем УИД в строковый формат: Строка(Ссылка.УникальныйИдентификатор()).
  3. Явно определяем состав и типы колонок таблицы значений перед передачей ее в параметр запроса.
← На главную