Разработка и Конфигурация · 10 мин
Как передать таблицу значений в запрос в 1С
Как передать таблицу значений в запрос 1С через временную таблицу и менеджер временных таблиц: код, примеры, типичные ошибки и проверка результата.
В языке запросов 1С нельзя напрямую обратиться к таблице значений как к параметру — запрос работает только с данными информационной базы и временными таблицами. Поэтому передача таблицы значений в запрос всегда выполняется в два этапа: сначала таблица значений помещается во временную таблицу с помощью конструкции ПОМЕСТИТЬ, затем эта временная таблица используется в основном запросе для соединений, отборов или группировок.
Такой подход применяется в типовых задачах: отбор документов по списку, сформированному программно; сравнение данных из файла с данными базы; расчёт по таблице, полученной из другого запроса или из внешнего источника. Механизм одинаково работает в обычных и управляемых формах, на толстом и тонком клиенте через серверный вызов.
Ниже разобран полный рабочий код, нюансы типизации колонок, ограничения платформы и типичные ошибки, из-за которых запрос возвращает пустой результат или падает с ошибкой.
Базовый принцип: временная таблица и ПОМЕСТИТЬ
Ключевая идея — параметр запроса может принимать таблицу значений, но использовать её можно только в конструкции ПОМЕСТИТЬ. Платформа выгружает содержимое таблицы значений во временную таблицу на сервере СУБД, и дальше с ней работают обычными соединениями и условиями.
Минимальный шаблон выглядит так: создаётся менеджер временных таблиц, он назначается запросу, первым пакетом выполняется помещение таблицы значений во временную таблицу, вторым — основная выборка с обращением к ней.
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст =
"ВЫБРАТЬ
| ТЗ.Номенклатура КАК Номенклатура,
| ТЗ.Количество КАК Количество
|ПОМЕСТИТЬ ВТ_Данные
|ИЗ
| &ТаблицаДанных КАК ТЗ
|;
|ВЫБРАТЬ
| ВТ.Номенклатура,
| ВТ.Количество,
| Цены.Цена
|ИЗ
| ВТ_Данные КАК ВТ
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних() КАК Цены
| ПО ВТ.Номенклатура = Цены.Номенклатура";
Запрос.УстановитьПараметр("ТаблицаДанных", ТаблицаДанных);
Результат = Запрос.Выполнить().Выгрузить();Обратите внимание: имя параметра в тексте запроса (&ТаблицаДанных) и имя, переданное в УстановитьПараметр, должны совпадать. Сама таблица значений должна быть создана и заполнена до выполнения запроса.
Как правильно подготовить таблицу значений
Таблица значений должна иметь явно описанные колонки с типами. Если колонку добавить без типа или заполнить значениями разных типов, платформа при выгрузке во временную таблицу может неявно привести типы, и соединение с полями базы данных перестанет работать или будет работать медленно.
ТаблицаДанных = Новый ТаблицаЗначений;
ТаблицаДанных.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
ТаблицаДанных.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)));
Строка = ТаблицаДанных.Добавить();
Строка.Номенклатура = СсылкаНаНоменклатуру;
Строка.Количество = 10;Для ссылочных колонок указывайте конкретный тип ссылки, а не составной «любая ссылка». Для строк задавайте длину через КвалификаторыСтроки — строка неограниченной длины во временной таблице затрудняет индексацию и соединения. Для дат уточняйте состав даты (дата или дата и время), иначе сравнение с реквизитами документов может не сработать из-за несовпадения точности.
Роль менеджера временных таблиц
Временная таблица существует только внутри менеджера временных таблиц. Если создать временную таблицу одним запросом без менеджера, она будет уничтожена сразу после выполнения, и второй запрос её не увидит — типичная причина ошибки «Таблица не найдена».
Один менеджер можно назначить нескольким объектам Запрос — это удобно, когда временные таблицы накапливаются поэтапно: сначала помещается таблица значений, потом промежуточный расчёт, затем финальная выборка. После использования менеджер следует закрыть методом Закрыть(), чтобы освободить ресурсы СУБД.
- 1Создайте таблицу значений с типизированными колонками и заполните данными
- 2Создайте МенеджерВременныхТаблиц и назначьте его объекту Запрос
- 3Напишите текст: ВЫБРАТЬ поля ПОМЕСТИТЬ ВТ ИЗ &ТЗ, затем основной запрос с соединением к ВТ
- 4Передайте таблицу через УстановитьПараметр с тем же именем
- 5Выполните запрос и проверьте результат выборкой или выгрузкой
- 6После работы закройте менеджер временных таблиц
Типовые сценарии использования
Отбор по списку значений из таблицы
Когда нужно отобрать документы или остатки по списку, собранному программно, таблица значений соединяется с таблицей базы по ключевому полю. Это надёжнее, чем передача массива в условие В (&Список), если помимо ключа нужны дополнительные данные — количество, цена, признак обработки.
Сравнение внешних данных с базой
При загрузке из Excel или CSV данные помещают в таблицу значений, передают в запрос и левым соединением ищут соответствия в справочнике. Строки, где поле справочника равно NULL, — это ненайденные позиции, их удобно вывести пользователю отдельным списком.
Многократное использование одной временной таблицы
Одну и ту же временную таблицу можно использовать в нескольких последующих запросах в рамках одного менеджера — например, сначала посчитать итоги, потом детализацию. Повторно передавать таблицу значений не требуется.
Сравнение вариантов
Подходит при нескольких колонках и повторном использовании данных; требует менеджера временных таблиц
Проще, если нужен отбор только по одному полю; не передаёт дополнительные данные
Для постоянных интеграций; избыточен для разовой передачи в запрос
Ограничения и производительность
Передача таблицы значений во временную таблицу — это физическая выгрузка данных на сервер СУБД. При объёмах в сотни тысяч строк операция занимает заметное время и память, поэтому не стоит передавать «на всякий случай» лишние колонки и строки — отсекайте их до запроса.
По умолчанию временная таблица создаётся без индексов. Если по ней выполняется соединение с крупной таблицей базы, добавьте индекс в конструкции ПОМЕСТИТЬ с помощью предложения ИНДЕКСИРОВАТЬ ПО — это заметно ускоряет соединение на больших объёмах.
// Фрагмент текста запроса с индексом:
// ПОМЕСТИТЬ ВТ_Данные
// ИЗ &ТаблицаДанных КАК ТЗ
// ИНДЕКСИРОВАТЬ ПО
// ТЗ.НоменклатураЕщё одно ограничение: таблицу значений нельзя передать в запрос, выполняемый в пакете с другими запросами через один вызов, если у запроса нет менеджера временных таблиц — пакетное выполнение не отменяет необходимость менеджера для временных таблиц.
Частые ошибки и их диагностика
Чаще всего встречаются три проблемы. Первая — пустой результат при внешне корректном коде: причина почти всегда в несовпадении типов колонки таблицы значений и поля базы (например, составной тип ссылки или строка вместо ссылки). Вторая — ошибка «Таблица не найдена»: запросы выполняются с разными менеджерами временных таблиц или без менеджера вообще. Третья — «Неверные параметры в операции сравнения»: тип колонки не приводится к типу поля соединения.
Как проверить результат
Выборка из ВТ возвращает то же число строк, что в таблице значений
Строк меньше или ноль — проверяйте типы колонок и заполнение ТЗ
Ключевые поля совпадают, NULL только у реально отсутствующих записей
Массовые NULL — несовпадение типов или значений ключей
Запрос отрабатывает за секунды на рабочем объёме
Минутное ожидание — добавьте индекс по полю соединения
FAQ
Можно ли передать таблицу значений в запрос без временной таблицы?
Нет. Язык запросов 1С умеет принимать таблицу значений только как источник конструкции ПОМЕСТИТЬ. Альтернатива — передать массив значений в условие В (&Массив), если нужен отбор по одному полю без дополнительных данных.
Почему запрос возвращает пустой результат, хотя таблица заполнена?
Наиболее вероятная причина — несовпадение типов: колонка таблицы значений имеет составной или неточный тип, а соединение идёт со ссылочным полем конкретного типа. Задайте колонке точный ОписаниеТипов и проверьте, что значения в строках соответствуют этому типу.
Нужно ли удалять временную таблицу после использования?
Явно удалять необязательно: временные таблицы уничтожаются при закрытии менеджера временных таблиц методом Закрыть(). Если менеджер долгоживущий и таблица больше не нужна, можно выполнить запрос с конструкцией УНИЧТОЖИТЬ ИмяТаблицы.
Можно ли передать таблицу значений с клиента на сервер для запроса?
Да, таблица значений сериализуется при вызове серверной процедуры, но при большом объёме это создаёт нагрузку на канал. В управляемых формах часто удобнее использовать динамический список или передавать только необходимые колонки и отфильтрованные строки.
Чем отличается передача массива от передачи таблицы значений?
Массив передаётся в параметр и используется в условии В (&Массив) — это отбор по одному полю. Таблица значений помещается во временную таблицу и позволяет соединяться по нескольким полям и переносить в запрос дополнительные данные: количества, цены, признаки.
Работает ли этот механизм в запросах к внешним источникам данных?
Механизм временных таблиц относится к запросам по данным информационной базы. Для внешних источников данных применяются собственные правила построения запросов, и передача таблицы значений туда напрямую не поддерживается.
Что важно запомнить
Таблица значений попадает в запрос только через временную таблицу: ПОМЕСТИТЬ + единый МенеджерВременныхТаблиц. Типизируйте колонки, индексируйте поля соединения и проверяйте результат на копии базы перед запуском в рабочей.