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

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

При разработке на платформе 1С:Предприятие 8 часто возникает ситуация, когда данные, уже находящиеся в памяти (например, в таблице значений на форме или полученные из внешнего источника), необходимо использовать в запросе для соединения с данными из базы. Напрямую передать объект типа ТаблицаЗначений в параметр запроса и работать с ним как с таблицей БД невозможно. Рассмотрим подробнее, как правильно реализовать этот механизм, разберем типичные ошибки и изучим продвинутые способы оптимизации.

Базовый алгоритм передачи таблицы значений

Основной принцип работы заключается в том, что таблица значений должна быть передана в запрос как параметр, а затем внутри самого текста запроса она должна быть помещена во временную таблицу. Только после этого к ней можно будет обращаться в последующих пакетах запроса для выбора данных или соединений.

Разберем по шагам стандартный процесс:

  1. Подготовка данных: Если ваша таблица является реквизитом формы, ее необходимо выгрузить в обычный объект ТаблицаЗначений.
  2. Установка параметра: Передаем выгруженную таблицу в запрос через метод УстановитьПараметр.
  3. Текст запроса: Используем инструкцию ПОМЕСТИТЬ для создания временной таблицы из параметра.

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


// 1. Получаем объект ТаблицаЗначений из реквизита формы
ТЗ_ДляЗапроса = ТаблицаЗначенийНаФорме.Выгрузить();

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

// 3. Устанавливаем параметры
Запрос.УстановитьПараметр("ВнешняяТЗ", ТЗ_ДляЗапроса);
Запрос.УстановитьПараметр("Период", ТекущаяДата());

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

Важность типизации колонок таблицы значений

Проанализируем критически важный момент: типизацию. Если вы создаете таблицу значений программно или получаете ее из внешних источников (например, при загрузке из Excel), колонки могут иметь неопределенный тип или тип Произвольный. Если такая таблица окажется пустой в момент передачи в запрос, система не сможет определить структуру временной таблицы и выдаст ошибку.

Чтобы этого избежать, всегда рекомендуется жестко типизировать колонки при создании ТаблицыЗначений. Выясним, как это сделать правильно с помощью объекта ОписаниеТипов:


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

// Описываем типы для колонок
МассивТиповСтрока = Новый Массив;
МассивТиповСтрока.Добавить(Тип("Строка"));
ОписаниеТипаСтрока = Новый ОписаниеТипов(МассивТиповСтрока, , Новый КвалификаторыСтроки(100));

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

// Добавляем колонки с типами
ТЗ.Колонки.Добавить("Артикул", ОписаниеТипаСтрока);
ТЗ.Колонки.Добавить("Количество", ОписаниеТипаЧисло);

Важный нюанс: Если в таблице значений используются составные типы данных, 1С создаст во временной таблице на уровне SQL несколько соответствующих полей. Это может снизить производительность, поэтому старайтесь использовать максимально простые и однозначные типы.

Оптимизация: Индексирование временных таблиц

Когда мы помещаем таблицу значений во временную таблицу (ВТ), система создает ее в оперативной памяти или в базе данных tempdb (для SQL-версий). Если вы планируете соединять эту ВТ с большими таблицами базы данных (например, с регистром бухгалтерии или регистром накопления), отсутствие индексов приведет к полному сканированию таблиц (Full Scan), что крайне медленно.

Рассмотрим ситуацию, где мы добавляем индекс прямо в тексте запроса:


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

Использование инструкции ИНДЕКСИРОВАТЬ ПО значительно ускоряет выполнение ЛЕВОГО СОЕДИНЕНИЯ или ВНУТРЕННЕГО СОЕДИНЕНИЯ по индексируемому полю.

Использование готовых механизмов БСП (Библиотеки Стандартных Подсистем)

В современных конфигурациях (таких как ERP, ЗУП 3.1, КА, БП 3.0) разработчики часто используют готовые модули для создания временных таблиц из ТЗ. Это избавляет от необходимости писать рутинный код по созданию МенеджераВременныхТаблиц и описанию структуры запроса вручную.

Например, в типовых решениях на базе БЗК (Библиотека Зарплаты и Кадров) можно встретить следующий подход:


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

Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос.Текст = "ВЫБРАТЬ * ИЗ ВТ_ВременныеДанные КАК ВТ";

Такой подход делает код более чистым и читаемым, делегируя обработку типов и создание имен колонок системным механизмам.

Ограничения и важные правила

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

Работа с ТЗ в Системе компоновки данных (СКД)

Выясним, как обстоят дела, если нужно вывести отчет. В СКД таблицу значений можно передать как Внешний набор данных. В этом случае нам не нужно писать ПОМЕСТИТЬ в тексте запроса. Мы просто регистрируем таблицу в процессоре компоновки по ее имени, и СКД сама строит запрос к этой таблице в памяти.

Это особенно удобно при реализации сложных отчетов, где часть данных рассчитывается сложными алгоритмами в коде, а часть выбирается из базы данных. Соединение этих данных внутри СКД работает эффективнее и гибче, чем ручное формирование временных таблиц.

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

← На главную