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

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

Таблица значений как параметр запроса в 1С

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

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

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

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

Когда таблицу передают параметром, а когда это лишнее

Приём оправдан, если источник данных находится вне информационной базы или уже получен в память: таблица загружена из Excel или CSV, сформирована обработкой, получена из СКД или предыдущего пакетного запроса. Типовые сценарии — подбор документов по списку номеров, сверка остатков с внешними данными, расчёт цен по загруженному прайсу.

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

Маршрут решения

Как выбрать действие

Данные загружены из файла или сформированы кодомПередавайте таблицу значений параметром и помещайте во временную таблицу
Все данные уже есть в таблицах базыПишите один запрос с соединениями, без параметра-таблицы
Таблица нужна в нескольких запросах подрядИспользуйте менеджер временных таблиц (МенеджерВременныхТаблиц)
Строк в таблице больше нескольких десятков тысячОцените объём памяти и рассмотрите пакетную обработку порциями

Подготовка таблицы значений

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

ТЗ = Новый ТаблицаЗначений;

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

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

НоваяСтрока = ТЗ.Добавить();

НоваяСтрока.Номенклатура = СсылкаНаТовар;

НоваяСтрока.Количество = 10;

Имена колонок таблицы значений станут именами полей временной таблицы в запросе. Используйте осмысленные имена без пробелов и спецсимволов — это упрощает текст запроса и уменьшает риск путаницы при соединениях.

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

Текст запроса: помещение таблицы во временную таблицу

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| ТЗ.Номенклатура КАК Номенклатура,

| ТЗ.Количество КАК Количество

|ПОМЕСТИТЬ ВТ_Товары

|ИЗ

| &ТЗ КАК ТЗ

|;

|

|ВЫБРАТЬ

| ВТ.Номенклатура КАК Номенклатура,

| ВТ.Количество КАК Количество,

| ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток

|ИЗ

| ВТ_Товары КАК ВТ

| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки

| ПО ВТ.Номенклатура = Остатки.Номенклатура";

Запрос.УстановитьПараметр("ТЗ", ТЗ);

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

Обратите внимание на синтаксис: источником в первом операторе выступает &ТЗ — имя параметра, а не имя переменной в коде. Псевдоним КАК ТЗ после параметра обязателен, через него обращаются к полям.

Индексация временной таблицы

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

ВЫБРАТЬ

ТЗ.Номенклатура КАК Номенклатура,

ТЗ.Количество КАК Количество

ПОМЕСТИТЬ ВТ_Товары

ИЗ

&ТЗ КАК ТЗ

ИНДЕКСИРОВАТЬ ПО

Номенклатура

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

Если соединение идёт по ссылочному полю, убедитесь, что колонка таблицы значений типизирована именно ссылкой на нужный справочник, а не составным типом. Соединение по составному типу часто не использует индекс и выполняется полным перебором.
ПЗ
Практическое замечание

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

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

МВТ = Новый МенеджерВременныхТаблиц;

Запрос1 = Новый Запрос;

Запрос1.МенеджерВременныхТаблиц = МВТ;

Запрос1.Текст = "ВЫБРАТЬ ТЗ.Номенклатура КАК Номенклатура ПОМЕСТИТЬ ВТ_Товары ИЗ &ТЗ КАК ТЗ";

Запрос1.УстановитьПараметр("ТЗ", ТЗ);

Запрос1.Выполнить();

Запрос2 = Новый Запрос;

Запрос2.МенеджерВременныхТаблиц = МВТ;

Запрос2.Текст = "ВЫБРАТЬ * ИЗ ВТ_Товары КАК ВТ";

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

Ограничения и риски

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

Второй риск — типы данных. Колонка с неограниченной строкой, переданная в соединение со строковым полем фиксированной длины, может привести к ошибке или неэффективному плану. Всегда задавайте квалификаторы: длину строки, точность числа.

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

Проверка результата и типичные ошибки

После выполнения запроса сверьте количество строк результата с количеством строк исходной таблицы. Если строк стало больше — вероятны дубли в соединяемых полях. Если меньше при левом соединении — проверьте, не потерялись ли строки из-за NULL в ключевых полях таблицы значений.

Типичные ошибки
01
Обращение к &ТЗ в условии ГДЕ без ПОМЕСТИТЬ — запрос падает с синтаксической ошибкой
02
Нетипизированные колонки таблицы значений — ошибка несовместимости типов или пустой результат соединения
03
Дубли ключей в таблице — размножение строк результата и неверные итоги
04
Отсутствие ЕСТЬNULL при левом соединении — NULL вместо нулей в числовых полях
05
Передача таблицы с сотнями тысяч строк одним куском — рост потребления памяти и медленное выполнение
Контрольные точки

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

Число строк результата
Норма

Равно числу строк исходной таблицы (или ожидаемо меньше при внутреннем соединении)

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

Строк больше исходных — дубли в ключах соединения

Числовые поля после левого соединения
Норма

Нет данных заменены на 0 через ЕСТЬNULL

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

Значения NULL ломают последующие расчёты

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

Запрос с индексом по полю соединения выполняется быстро

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

Резкое замедление при росте таблицы — нет индекса или составной тип поля

FAQ

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

Нет. Параметр-таблица допустим только как источник оператора ВЫБРАТЬ с ПОМЕСТИТЬ. Использовать его напрямую в условиях или соединениях синтаксис языка запросов не позволяет.

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

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

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

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

Как передать результат одного запроса в другой запрос?

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

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

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

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

Жёсткого ограничения платформа не накладывает, но практический предел определяется памятью сервера и настройками СУБД. Для таблиц в десятки тысяч строк и больше надёжнее обрабатывать данные порциями в цикле.

Итог

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

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