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

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

Как передать список значений в запрос 1С

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

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

Типичная ситуация: пользователь отобрал на форме несколько контрагентов, и нужно одним запросом получить по ним остатки, обороты или документы. Формировать запрос в цикле — плохое решение: каждый вызов Запрос.Выполнить() — это отдельное обращение к СУБД, и на больших объёмах производительность падает в разы. Один запрос с параметром-списком решает задачу быстрее и проще в сопровождении.

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

Базовый способ: параметр и оператор В

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

Пример кода:

МассивКонтрагентов = Новый Массив;

МассивКонтрагентов.Добавить(Контрагент1);

МассивКонтрагентов.Добавить(Контрагент2);

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

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

"ВЫБРАТЬ

| РеализацияТоваровУслуг.Ссылка КАК Ссылка,

| РеализацияТоваровУслуг.Контрагент КАК Контрагент

|ИЗ

| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг

|ГДЕ

| РеализацияТоваровУслуг.Контрагент В (&СписокКонтрагентов)";

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

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

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

Передача списка значений из формы

Когда отбор делает пользователь, значения обычно собираются в элемент формы «СписокЗначений» или в динамический список с множественным выбором. Объект СписокЗначений передаётся в параметр запроса напрямую, без преобразования в массив — платформа корректно обрабатывает оба типа.

Если список формируется из табличной части или таблицы формы, удобно выгрузить нужную колонку методом ВыгрузитьКолонку() объекта ТаблицаЗначений — результатом будет массив, готовый к передаче в параметр:

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

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

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

"ВЫБРАТЬ

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

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

|ИЗ

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

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

Обратите внимание: в примере параметр используется в параметрах виртуальной таблицы остатков, а не в секции ГДЕ. Это важно для производительности — отбор накладывается до вычисления итогов, а не после.

Отбор по иерархии: В ИЕРАРХИИ

Если нужно отобрать не только сами элементы списка, но и все их подчинённые элементы (например, группы номенклатуры вместе с содержимым), используется оператор В ИЕРАРХИИ. Синтаксис параметра не меняется — передаётся тот же массив или список, но теперь в него можно включать группы справочника.

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

"ВЫБРАТЬ

| Номенклатура.Ссылка КАК Ссылка

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

| Номенклатура.Ссылка В ИЕРАРХИИ(&СписокГрупп)";

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

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

Таблица значений как параметр: временные таблицы

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

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

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

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

// ... заполнение ТЗ ...

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

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

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

"ВЫБРАТЬ

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

| ТЗ.Склад КАК Склад

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

|ИЗ

| &ТЗ КАК ТЗ

|;

|ВЫБРАТЬ

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

| Остатки.Склад КАК Склад,

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

|ИЗ

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

| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Отбор КАК Отбор

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

| И Остатки.Склад = Отбор.Склад";

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

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

Три обязательных условия для этого способа: колонкам таблицы значений нужно явно задать типы (иначе возможны ошибки преобразования), для запроса должен быть создан МенеджерВременныхТаблиц, а имя параметра в тексте (&ТЗ) должно совпадать с именем в УстановитьПараметр.

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

Массив или список + оператор В

Подходит для отбора по одному полю. Простой код, минимум подготовки. Ограничение — только одно поле отбора.

Таблица значений + временная таблица

Подходит для отбора по комбинации полей и больших наборов данных. Требует описания типов колонок и менеджера временных таблиц.

Список в параметрах виртуальной таблицы

Оптимально для регистров: отбор выполняется до расчёта итогов. Работает только с виртуальными таблицами регистров.

Списки в СКД и динамических списках

В системе компоновки данных передавать список вручную через УстановитьПараметр обычно не нужно: достаточно объявить параметр в наборе данных, задать ему свойство «Доступен список значений» и связать с отбором. Пользователь тогда сам заполняет список в настройках отчёта, а СКД формирует условие В автоматически.

Если параметр всё же устанавливается программно, используется объект настроек компоновки:

ПараметрСКД = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("СписокКонтрагентов");

ПараметрСКД.Использование = Истина;

ПараметрСКД.Значение = СписокКонтрагентов;

В динамических списках аналогично: параметр объявляется в тексте запроса списка, а значение присваивается через Список.Параметры.УстановитьЗначениеПараметра("Имя", Значение). Переданный массив или список значений будет корректно обработан условием В.

Ограничения и производительность

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

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

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

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

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

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

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

Результат запроса
Норма

Выборка содержит строки по элементам списка

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

Пустой результат при заведомо существующих данных — проверьте типы значений в списке

Состав отобранных значений
Норма

Все значения поля отбора входят в переданный список

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

Присутствуют лишние элементы — возможно, условие В написано не по тому полю

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

Рост времени умеренный при увеличении списка

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

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

Для отладки удобно временно вывести содержимое списка через цикл и Сообщить() или выполнить тот же запрос в консоли запросов с теми же параметрами. Если в консоли результат правильный, а в коде пустой — проблема почти всегда в типе или составе передаваемого параметра.

Итог

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

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

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

Можно ли передать в параметр список значений напрямую, без массива?

Да, объект СписокЗначений передаётся в УстановитьПараметр без преобразования. Платформа сама обрабатывает его в операторе В так же, как массив. Важно только, чтобы значения элементов списка были нужного типа.

Почему запрос с условием В возвращает пустой результат?

Чаще всего тип значений в списке не совпадает с типом поля: например, переданы строки или коды вместо ссылок. Также проверьте, что параметр установлен до вызова Выполнить() и имя параметра в тексте совпадает с именем в УстановитьПараметр.

Как передать список для отбора по двум полям одновременно?

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

Есть ли ограничение на количество элементов в списке?

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

Как отобрать по списку с учётом иерархии справочника?

Используйте оператор В ИЕРАРХИИ (&Список) — в список можно включать группы, и в результат попадут все подчинённые им элементы. Оператор применим только к иерархическим справочникам и планам видов характеристик.

Нужно ли удалять дубликаты из списка перед передачей?

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