К статье
Практический материал

Разработка и Конфигурация · 10 мин

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

Как передать таблицу значений в запрос 1С через временную таблицу и менеджер временных таблиц: код, примеры, типичные ошибки и проверка результата.

В языке запросов 1С нельзя напрямую обратиться к таблице значений как к параметру — запрос работает только с данными информационной базы и временными таблицами. Поэтому передача таблицы значений в запрос всегда выполняется в два этапа: сначала таблица значений помещается во временную таблицу с помощью конструкции ПОМЕСТИТЬ, затем эта временная таблица используется в основном запросе для соединений, отборов или группировок.

Такой подход применяется в типовых задачах: отбор документов по списку, сформированному программно; сравнение данных из файла с данными базы; расчёт по таблице, полученной из другого запроса или из внешнего источника. Механизм одинаково работает в обычных и управляемых формах, на толстом и тонком клиенте через серверный вызов.

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

Базовый принцип: временная таблица и ПОМЕСТИТЬ

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

Минимальный шаблон выглядит так: создаётся менеджер временных таблиц, он назначается запросу, первым пакетом выполняется помещение таблицы значений во временную таблицу, вторым — основная выборка с обращением к ней.

bsl
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст =
"ВЫБРАТЬ
| ТЗ.Номенклатура КАК Номенклатура,
| ТЗ.Количество КАК Количество
|ПОМЕСТИТЬ ВТ_Данные
|ИЗ
| &ТаблицаДанных КАК ТЗ
|;
|ВЫБРАТЬ
| ВТ.Номенклатура,
| ВТ.Количество,
| Цены.Цена
|ИЗ
| ВТ_Данные КАК ВТ
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних() КАК Цены
| ПО ВТ.Номенклатура = Цены.Номенклатура";
Запрос.УстановитьПараметр("ТаблицаДанных", ТаблицаДанных);
Результат = Запрос.Выполнить().Выгрузить();

Обратите внимание: имя параметра в тексте запроса (&ТаблицаДанных) и имя, переданное в УстановитьПараметр, должны совпадать. Сама таблица значений должна быть создана и заполнена до выполнения запроса.

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

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

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

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

Для ссылочных колонок указывайте конкретный тип ссылки, а не составной «любая ссылка». Для строк задавайте длину через КвалификаторыСтроки — строка неограниченной длины во временной таблице затрудняет индексацию и соединения. Для дат уточняйте состав даты (дата или дата и время), иначе сравнение с реквизитами документов может не сработать из-за несовпадения точности.

Роль менеджера временных таблиц

Временная таблица существует только внутри менеджера временных таблиц. Если создать временную таблицу одним запросом без менеджера, она будет уничтожена сразу после выполнения, и второй запрос её не увидит — типичная причина ошибки «Таблица не найдена».

Один менеджер можно назначить нескольким объектам Запрос — это удобно, когда временные таблицы накапливаются поэтапно: сначала помещается таблица значений, потом промежуточный расчёт, затем финальная выборка. После использования менеджер следует закрыть методом Закрыть(), чтобы освободить ресурсы СУБД.

Порядок действий
  1. 1
    Создайте таблицу значений с типизированными колонками и заполните данными
  2. 2
    Создайте МенеджерВременныхТаблиц и назначьте его объекту Запрос
  3. 3
    Напишите текст: ВЫБРАТЬ поля ПОМЕСТИТЬ ВТ ИЗ &ТЗ, затем основной запрос с соединением к ВТ
  4. 4
    Передайте таблицу через УстановитьПараметр с тем же именем
  5. 5
    Выполните запрос и проверьте результат выборкой или выгрузкой
  6. 6
    После работы закройте менеджер временных таблиц

Типовые сценарии использования

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

Когда нужно отобрать документы или остатки по списку, собранному программно, таблица значений соединяется с таблицей базы по ключевому полю. Это надёжнее, чем передача массива в условие В (&Список), если помимо ключа нужны дополнительные данные — количество, цена, признак обработки.

Сравнение внешних данных с базой

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

Многократное использование одной временной таблицы

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

Сравнение вариантов

Таблица значений через ПОМЕСТИТЬ

Подходит при нескольких колонках и повторном использовании данных; требует менеджера временных таблиц

Массив в условии В (&Массив)

Проще, если нужен отбор только по одному полю; не передаёт дополнительные данные

Внешний источник данных

Для постоянных интеграций; избыточен для разовой передачи в запрос

Ограничения и производительность

Передача таблицы значений во временную таблицу — это физическая выгрузка данных на сервер СУБД. При объёмах в сотни тысяч строк операция занимает заметное время и память, поэтому не стоит передавать «на всякий случай» лишние колонки и строки — отсекайте их до запроса.

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

bsl
// Фрагмент текста запроса с индексом:
// ПОМЕСТИТЬ ВТ_Данные
// ИЗ &ТаблицаДанных КАК ТЗ
// ИНДЕКСИРОВАТЬ ПО
// ТЗ.Номенклатура

Ещё одно ограничение: таблицу значений нельзя передать в запрос, выполняемый в пакете с другими запросами через один вызов, если у запроса нет менеджера временных таблиц — пакетное выполнение не отменяет необходимость менеджера для временных таблиц.

Частые ошибки и их диагностика

Чаще всего встречаются три проблемы. Первая — пустой результат при внешне корректном коде: причина почти всегда в несовпадении типов колонки таблицы значений и поля базы (например, составной тип ссылки или строка вместо ссылки). Вторая — ошибка «Таблица не найдена»: запросы выполняются с разными менеджерами временных таблиц или без менеджера вообще. Третья — «Неверные параметры в операции сравнения»: тип колонки не приводится к типу поля соединения.

Типичные ошибки
01
Разные менеджеры временных таблиц у двух запросов — вторая выборка не видит ВТ и падает с ошибкой
02
Колонка добавлена без типа — соединение по ссылке не срабатывает, результат пустой
03
Опечатка в имени параметра между текстом запроса и УстановитьПараметр — ошибка при выполнении
04
Передача всей таблицы с лишними колонками и строками — лишняя нагрузка на СУБД
05
Отсутствие ИНДЕКСИРОВАТЬ ПО при соединении с большой таблицей — запрос выполняется минутами
Контрольные точки

Как проверить результат

Содержимое временной таблицы
Норма

Выборка из ВТ возвращает то же число строк, что в таблице значений

Тревожный признак

Строк меньше или ноль — проверяйте типы колонок и заполнение ТЗ

Соединение с таблицей базы
Норма

Ключевые поля совпадают, NULL только у реально отсутствующих записей

Тревожный признак

Массовые NULL — несовпадение типов или значений ключей

Время выполнения
Норма

Запрос отрабатывает за секунды на рабочем объёме

Тревожный признак

Минутное ожидание — добавьте индекс по полю соединения

FAQ

Можно ли передать таблицу значений в запрос без временной таблицы?

Нет. Язык запросов 1С умеет принимать таблицу значений только как источник конструкции ПОМЕСТИТЬ. Альтернатива — передать массив значений в условие В (&Массив), если нужен отбор по одному полю без дополнительных данных.

Почему запрос возвращает пустой результат, хотя таблица заполнена?

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

Нужно ли удалять временную таблицу после использования?

Явно удалять необязательно: временные таблицы уничтожаются при закрытии менеджера временных таблиц методом Закрыть(). Если менеджер долгоживущий и таблица больше не нужна, можно выполнить запрос с конструкцией УНИЧТОЖИТЬ ИмяТаблицы.

Можно ли передать таблицу значений с клиента на сервер для запроса?

Да, таблица значений сериализуется при вызове серверной процедуры, но при большом объёме это создаёт нагрузку на канал. В управляемых формах часто удобнее использовать динамический список или передавать только необходимые колонки и отфильтрованные строки.

Чем отличается передача массива от передачи таблицы значений?

Массив передаётся в параметр и используется в условии В (&Массив) — это отбор по одному полю. Таблица значений помещается во временную таблицу и позволяет соединяться по нескольким полям и переносить в запрос дополнительные данные: количества, цены, признаки.

Работает ли этот механизм в запросах к внешним источникам данных?

Механизм временных таблиц относится к запросам по данным информационной базы. Для внешних источников данных применяются собственные правила построения запросов, и передача таблицы значений туда напрямую не поддерживается.

Итог

Что важно запомнить

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