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