Как задать тип колонки таблицы значений во внешней базе через COM-соединение для передачи в запрос?

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

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

Разберем по шагам, как правильно создать объект ТаблицаЗначений в контексте внешней базы, сформировать для его колонок ОписаниеТипов с нужными квалификаторами и успешно выполнить запрос.

Причина возникновения ошибки и требования платформы

Рассмотрим подробнее механизм работы запросов с временными таблицами. Конструкция языка запросов ПОМЕСТИТЬ Вт_Таблица ИЗ &ТЗ КАК ТЗ опирается на строгую структуру полей. Менеджер базы данных создает временную таблицу в СУБД на основе метаданных колонок переданного объекта ТаблицаЗначений.

В случае работы через COM действуют два ключевых правила:

  1. Изоляция контекстов: объект ТаблицаЗначений, созданный в текущей информационной базе, не может быть напрямую прочитан внешним COM-запросом. Таблица должна быть создана непосредственно в контексте внешней базы через метод NewObject соединения.
  2. Однозначная типизация: каждая колонка таблицы должна иметь строго определенный тип (строка с фиксированной/переменной длиной, дата определенного формата, число заданной разрядности). Неограниченная длина строк или отсутствие типа вызовут ошибку при выполнении запроса либо наложат жесткие ограничения на соединения таблиц и группировки.

Создание типов и квалификаторов во внешней базе

Выясним причину сложности: в текущей базе нельзя просто использовать локальный конструктор Новый ОписаниеТипов(...), так как типы данных одного экземпляра приложения 1С несовместимы с другим через COM. Все объекты описания типов и квалификаторов необходимо создавать через COM-соединение.

Посмотрим на синтаксис инициализации различных типов данных во внешней базе:

1. Описание типа «Строка»:

Для строковых колонок обязательно создаем квалификатор строки, задавая длину и допустимость переменной длины.


// Создаем квалификатор строки: длина 50, переменная длина
КвалСтроки = УТ.NewObject("КвалификаторыСтроки", 50, УТ.ДопустимаяДлина.Переменная);
// Создаем описание типа
ТипСтрока = УТ.NewObject("ОписаниеТипов", "Строка", , КвалСтроки);

2. Описание типа «Дата»:

Для дат указывается квалификатор даты (дата и время или только дата).


// Создаем квалификатор даты (Дата и время)
КвалДаты = УТ.NewObject("КвалификаторыДаты", УТ.ЧастиДаты.ДатаВремя);
// Создаем описание типа
ТипДата = УТ.NewObject("ОписаниеТипов", "Дата", , , КвалДаты);

3. Описание типа «Число»:

Для числовых значений задаются общая длина, точность и знак.


// Длина 15, точность 2, неотрицательное
КвалЧисла = УТ.NewObject("КвалификаторыЧисла", 15, 2, УТ.ДопустимыйЗнак.Неотрицательный);
ТипЧисло = УТ.NewObject("ОписаниеТипов", "Число", КвалЧисла);

Полный пример выполнения запроса к внешней базе через COM

Объединим все этапы в единый программный блок. Подключимся к внешней базе, сформируем типизированную таблицу значений, заполним ее строками и передадим в запрос с созданием временной таблицы.


// 1. Устанавливаем COM-соединение с внешней базой
COMОбъект = Новый COMObject("V83.COMConnector");
УТ = COMОбъект.Connect("Srvr=""server-1c"";Ref=""base_name"";Usr=""Администратор"";Pwd=""password"";");

// 2. Создаем описания типов через COM-соединение
КвалСтроки = УТ.NewObject("КвалификаторыСтроки", 50, УТ.ДопустимаяДлина.Переменная);
ТипСтрока  = УТ.NewObject("ОписаниеТипов", "Строка", , КвалСтроки);

КвалДаты   = УТ.NewObject("КвалификаторыДаты", УТ.ЧастиДаты.ДатаВремя);
ТипДата    = УТ.NewObject("ОписаниеТипов", "Дата", , , КвалДаты);

// 3. Создаем типизированную ТаблицуЗначений во внешней базе
ТЗВнешняя = УТ.NewObject("ТаблицаЗначений");
ТЗВнешняя.Колонки.Добавить("НомерСтарый", ТипСтрока);
ТЗВнешняя.Колонки.Добавить("ДатаСборки",  ТипДата);

// 4. Заполняем таблицу данными
НоваяСтрока = ТЗВнешняя.Добавить();
НоваяСтрока.НомерСтарый = "А-00125";
НоваяСтрока.ДатаСборки  = ТекущаяДата();

// 5. Формируем и выполняем запрос
МЗапрос = УТ.NewObject("Запрос");
МЗапрос.Текст = 
"ВЫБРАТЬ
|	ТЗ.НомерСтарый КАК Номер,
|	ТЗ.ДатаСборки КАК ДатаСборки
|ПОМЕСТИТЬ Вт_Сборки
|ИЗ
|	&ТЗ КАК ТЗ
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
|	Вт_Сборки.Номер КАК Номер,
|	Вт_Сборки.ДатаСборки КАК ДатаСборки
|ИЗ
|	Вт_Сборки КАК Вт_Сборки";

МЗапрос.УстановитьПараметр("ТЗ", ТЗВнешняя);
РезультатЗапроса = МЗапрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
	// Обработка полученных данных
КонецЦикла;

Оптимизация передачи больших объемов данных

Проанализируем производительность приведенного подхода. Построчное заполнение таблицы значений во внешней базе через COM (ТЗВнешняя.Добавить() в цикле на стороне текущей базы) работает медленно на объемах в тысячи строк. Каждое обращение к полю и строке COM-объекта порождает сетевой вызов (marshalling).

Для ускорения передачи больших массивов данных рекомендуется использовать альтернативные варианты:

  1. Сериализация через XML/XDTO: таблица значений создается и типизируется локально, выгружается в XML-строку с помощью СериализаторXDTO и передается одной строкой во внешнюю базу, где восстанавливается через УТ.СериализаторXDTO.ПрочитатьXML(...).
  2. Использование строкового представления внутреннего формата: для таблиц с примитивными типами данных локальную ТЗ можно выгрузить функцией ЗначениеВСтрокуВнутр(ЛокальнаяТЗ) и распаковать во внешней базе вызовом УТ.ЗначениеИзСтрокиВнутр(СтрокаДанных).
← На главную