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

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

Как вставить таблицу значений в запрос 1С

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

Передача таблицы значений в запрос — стандартный приём в 1С, когда нужно отфильтровать данные базы по списку, сформированному в коде, или соединить результаты обработки с реальными регистрами и справочниками. Платформа поддерживает два способа: передать таблицу как параметр запроса и обратиться к ней через конструкцию «&ТЗ», либо поместить её во временную таблицу менеджера временных таблиц и работать с ней как с обычной таблицей в пакетном запросе.

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

Важное ограничение: таблицу значений нельзя вставить в текст запроса «как есть», конкатенацией строк. Платформа работает только через параметры или временные таблицы — это защищает от ошибок типизации и делает запрос предсказуемым для оптимизатора СУБД.

Передача таблицы значений параметром запроса

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

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

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

"ВЫБРАТЬ

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

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

|ПОМЕСТИТЬ ВТ_Данные

|ИЗ

| &ТЗ КАК ТЗ

|;

|ВЫБРАТЬ

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

| Остатки.КоличествоОстаток

|ИЗ

| ВТ_Данные КАК ВТ

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

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

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

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

Обратите внимание: имена полей в запросе должны совпадать с именами колонок таблицы значений. Если колонка называется «Товар», а в запросе вы пишете «ТЗ.Номенклатура», получите ошибку «Поле не найдено». Типы колонок тоже имеют значение — желательно, чтобы колонка была типизирована явно через Новый ОписаниеТипов(...), иначе при пустой таблице платформа может не определить тип поля.

Помещение таблицы во временную таблицу через менеджер

Когда таблицу нужно использовать в нескольких запросах пакета или соединять с большими выборками, лучше поместить её во временную таблицу. Для этого создаётся МенеджерВременныхТаблиц, назначается запросу, а таблица помещается конструкцией «ПОМЕСТИТЬ».

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

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

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

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

"ВЫБРАТЬ

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

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

|ПОМЕСТИТЬ ВТ_Отбор

|ИЗ

| &ТЗ КАК ТЗ

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

| Номенклатура";

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

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

После выполнения временная таблица «ВТ_Отбор» живёт в менеджере и доступна всем последующим запросам, которым назначен тот же менеджер. Это удобно для многоэтапной обработки: сначала отобрали данные из таблицы значений, затем соединили с остатками, затем — с ценами.

Конструкция «ИНДЕКСИРОВАТЬ ПО» создаёт индекс временной таблицы по указанным полям. На больших таблицах (тысячи строк) это заметно ускоряет соединения, потому что СУБД сможет использовать поиск по индексу вместо полного перебора.

Порядок действий
  1. 1
    Создайте таблицу значений и явно типизируйте колонки через ОписаниеТипов
  2. 2
    Создайте МенеджерВременныхТаблиц и назначьте его запросу
  3. 3
    Напишите запрос с ПОМЕСТИТЬ ВТ_Имя ИЗ &ТЗ и добавьте ИНДЕКСИРОВАТЬ ПО по полям соединения
  4. 4
    Установите параметр ТЗ и выполните запрос
  5. 5
    В последующих запросах с тем же менеджером обращайтесь к временной таблице по имени

Соединение таблицы значений с данными базы

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

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

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

Если таблица значений содержит дубли по ключевому полю, соединение размножит строки результата. Перед передачей в запрос сверните таблицу методом Свернуть() или добавьте СГРУППИРОВАТЬ ПО в запрос — это частая причина «задвоения» итогов.
ПЗ
Практическое замечание

Фильтрация без соединения: условие «В»

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

МассивНоменклатуры = ТаблицаЗначений.ВыгрузитьКолонку("Номенклатура");

Запрос.УстановитьПараметр("Список", МассивНоменклатуры);

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

"ВЫБРАТЬ

| Остатки.Номенклатура,

| Остатки.КоличествоОстаток

|ИЗ

| РегистрНакопления.ТоварыНаСкладах.Остатки(, Номенклатура В (&Список)) КАК Остатки";

Однако если нужны ещё и данные из таблицы значений (количество, цены, комментарии из файла), массив не поможет — требуется полноценная передача таблицы и соединение. Кроме того, условие «В» с очень большим массивом может работать медленнее соединения с проиндексированной временной таблицей.

Сравнение вариантов

Массив в условии В

Подходит для простого отбора по одному полю; не передаёт остальные колонки таблицы

Параметр &ТЗ напрямую

Подходит для разового соединения; не индексируется, сложно переиспользовать в пакете

Временная таблица через менеджер

Подходит для пакетных запросов и больших объёмов; требует явного управления менеджером

Типичные ошибки и ограничения

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

Отдельный случай — ссылочные значения разных конфигураций или составные типы. Если колонка содержит и справочники, и документы, соединение с конкретной таблицей справочника отработает корректно только для совпадающих ссылок, а оптимизатор может построить неэффективный план. По возможности держите колонки однотипными.

Помните про время жизни временных таблиц: они существуют, пока существует менеджер временных таблиц. Если менеджер — локальная переменная процедуры, после выхода из неё таблицы уничтожаются. Также не забывайте уничтожать ненужные временные таблицы в длинных пакетах командой «УНИЧТОЖИТЬ», чтобы не расходовать память сервера СУБД.

Типичные ошибки
01
Колонка без типа: запрос падает или соединение не находит совпадений — задавайте ОписаниеТипов при создании колонки
02
Дубли в таблице значений: результат соединения размножается, итоги завышаются — сворачивайте таблицу заранее
03
Опечатка в имени колонки: ошибка «Поле не найдено» — сверяйте имена в ТЗ и в тексте запроса
04
Потеря менеджера временных таблиц: второй запрос не видит ВТ — назначайте один менеджер всем запросам пакета
05
Соединение по неиндексированному полю на большой таблице: запрос выполняется минутами — добавляйте ИНДЕКСИРОВАТЬ ПО

Проверка результата и отладка

После передачи таблицы полезно проверить, что она попала в запрос полностью. Самый простой способ — выполнить выборку «ВЫБРАТЬ * ИЗ ВТ_Отбор» и сравнить количество строк с исходной таблицей значений. Расхождение означает проблему на этапе передачи параметра.

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

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

Контрольные точки

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

Количество строк во временной таблице
Норма

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

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

Меньше или больше — проверяйте передачу параметра и дубли

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

NULL только у строк, которых реально нет в базе

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

NULL у большинства строк — не совпадают типы или значения ключей

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

Секунды на таблице в тысячи строк

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

Минуты — нет индекса по полю соединения

Частые вопросы

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

Да, сам запрос всегда выполняется на сервере. Таблица значений должна быть сформирована в серверном контексте или передана туда через параметр серверной процедуры. На тонком клиенте таблица значений недоступна — используйте массив структур и собирайте таблицу на сервере.

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

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

Почему запрос не видит временную таблицу во втором запросе?

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

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

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

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

В тексте запроса перечислите только нужные поля в списке выборки: «ВЫБРАТЬ ТЗ.Номенклатура, ТЗ.Количество ИЗ &ТЗ КАК ТЗ». Лишние колонки просто не попадут во временную таблицу, это также экономит память.

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

Да. Передайте обе через параметры (&ТЗ1, &ТЗ2), поместите каждую в свою временную таблицу и соедините их между собой или с таблицами базы. Это рабочий приём для сопоставления двух внешних источников данных.

Итог

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

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