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