Как передать таблицу значений в качестве параметра в запрос 1С

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

Передача таблицы значений в запрос 1С — частая задача при разработке, когда требуется соединить предварительно рассчитанные в памяти данные с таблицами базы данных или выполнить по ним сложную группировку. Разберем по шагам, как правильно подготовить таблицу значений, передать ее в параметры запроса и обработать на стороне СУБД.

Главное правило: обязательная типизация колонок

Платформа 1С:Предприятие не позволяет передавать в запрос таблицу значений с произвольными (нетипизированными) колонками. Если создать колонку простым вызовом Таблица.Колонки.Добавить("Номенклатура") без указания второго параметра ОписаниеТипов, при выполнении запроса возникнет ошибка времени выполнения.

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

  1. Допустимые типы: примитивные типы (Число, Строка, Дата, Булево), а также ссылочные типы конфигурации (СправочникСсылка, ДокументСсылка, ПеречислениеСсылка и др.). Допускаются и составные типы, если каждый тип в отдельности поддерживается платформой в запросах.
  2. Недопустимые типы: объектные типы (СправочникОбъект, ДокументОбъект), коллекции (Массив, Структура, Соответствие) и бинарные данные. Их использование приведет к исключению.
  3. Ограничение длины строк: при создании строковых колонок обязательно указывайте КвалификаторыСтроки фиксированной длины. Неограниченные строки переносятся в СУБД как неограниченные поля, что сделает невозможным операции соединения (СОЕДИНЕНИЕ), группировки (СГРУППИРОВАТЬ ПО), отбора уникальных (РАЗЛИЧНЫЕ) и сортировки (УПОРЯДОЧИТЬ ПО).

Способ 1. Программное создание и типизация таблицы значений

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


// 1. Создаем таблицу значений и описываем типы колонок
ТЗ = Новый ТаблицаЗначений;

МассивТиповСсылка = Новый Массив;
МассивТиповСсылка.Добавить(Тип("СправочникСсылка.Номенклатура"));
ОписаниеТипаНоменклатура = Новый ОписаниеТипов(МассивТиповСсылка);
ТЗ.Колонки.Добавить("Номенклатура", ОписаниеТипаНоменклатура);

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

// 2. Заполняем таблицу данными
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.Номенклатура = СсылкаНаТовар;
НоваяСтрока.Количество = 10;

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

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

Способ 2. Типизация уже существующей нетипизированной таблицы

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


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

// Переносим данные из исходной нетипизированной таблицы
Для Каждого СтрИсходная Из ИсходнаяТЗ Цикл
	ЗаполнитьЗначенияСвойств(ТипизированнаяТЗ.Добавить(), СтрИсходная);
КонецЦикла;

// Передаем типизированную таблицу в запрос
Запрос.УстановитьПараметр("ВнешняяТЗ", ТипизированнаяТЗ);

Особенности работы с таблицей значений в тексте запроса

Выясним важные технические нюансы работы с переданной таблицей значений:

  1. Только через конструкцию ПОМЕСТИТЬ: переданную через параметр таблицу значений нельзя сразу соединять с другими таблицами базы (например, писать ЛЕВОЕ СОЕДИНЕНИЕ &ВнешняяТЗ). Таблицу необходимо первым пакетом запроса поместить во временную таблицу.
  2. Индексация полей: если во временной таблице содержится большой объем строк и планируется соединение с таблицами базы данных, обязательно используйте инструкцию ИНДЕКСИРОВАТЬ ПО:

ВЫБРАТЬ
	ВхТЗ.Номенклатура КАК Номенклатура,
	ВхТЗ.Количество КАК Количество
ПОМЕСТИТЬ ВТ_ИсходныеДанные
ИЗ
	&ВнешняяТЗ КАК ВхТЗ
ИНДЕКСИРОВАТЬ ПО
	Номенклатура

Альтернативные подходы

Посмотрим на альтернативные варианты, которые могут оказаться эффективнее таблицы значений:

  1. Передача простого массива: если вам требуется передать список ссылок только для фильтрации в условии ГДЕ Поле В (&МассивСсылок), не используйте таблицу значений — передавайте стандартный Массив.
  2. Менеджер временных таблиц: если данные формируются другим запросом в коде, не выгружайте их в промежуточную таблицу значений методом Выгрузить(). Используйте МенеджерВременныхТаблиц, чтобы временная таблица сохранилась в контексте сеанса без лишней нагрузки на оперативную память сервера.
← На главную