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