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