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

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

1С: список как параметр запроса

Как передать список значений или массив как параметр запроса в 1С: оператор В, В ИЕРАРХИИ, работа с таблицей значений, типичные ошибки и примеры кода.

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

Язык запросов 1С поддерживает проверку вхождения значения в список через оператор В. В качестве параметра при этом можно передать массив, список значений или таблицу значений — платформа сама развернёт коллекцию в набор значений на стороне СУБД. Это работает и в файловом, и в клиент-серверном варианте.

Ключевой момент, который часто упускают: параметр-список должен быть заполнен. Пустой список в условии В (&Список) приведёт к тому, что запрос не вернёт ни одной строки, и это не всегда очевидно при отладке. Ниже разобраны рабочие приёмы, ограничения и типичные ошибки.

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

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

bsl
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Наименование КАК Наименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка В (&СписокТоваров)";

СписокТоваров = Новый СписокЗначений;
СписокТоваров.Добавить(Товар1);
СписокТоваров.Добавить(Товар2);

Запрос.УстановитьПараметр("СписокТоваров", СписокТоваров);
Результат = Запрос.Выполнить().Выгрузить();

Аналогично работает и массив — многие разработчики предпочитают его, потому что массив легче формируется при обходе данных и занимает меньше памяти:

bsl
МассивКонтрагентов = Новый Массив;
Для Каждого Строка Из ТаблицаОтбора Цикл
 МассивКонтрагентов.Добавить(Строка.Контрагент);
КонецЦикла;
Запрос.УстановитьПараметр("Контрагенты", МассивКонтрагентов);

Обратите внимание: в условии В список обязательно заключается в круглые скобки вместе с параметром — В (&Список). Запись без скобок является синтаксической ошибкой.

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

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

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

Массив

Универсальный и лёгкий вариант для отбора по одному полю. Не подходит для составного отбора по нескольким колонкам.

Список значений

Удобен, когда список приходит из интерфейса (например, из элемента формы). Для больших объёмов работает медленнее массива при заполнении.

Таблица значений через временную таблицу

Оптимальна для больших списков и отбора по нескольким полям. Требует больше кода: помещение во временную таблицу, индексация, соединение.

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

bsl
Запрос.Текст =
"ВЫБРАТЬ
| ТЗ.Номенклатура КАК Номенклатура,
| ТЗ.Склад КАК Склад
|ПОМЕСТИТЬ ВТ_Отбор
|ИЗ
| &ТЗ КАК ТЗ
|;
|ВЫБРАТЬ
| Остатки.Номенклатура,
| Остатки.Склад,
| Остатки.КоличествоОстаток
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Отбор КАК Отбор
| ПО Остатки.Номенклатура = Отбор.Номенклатура
| И Остатки.Склад = Отбор.Склад";
Запрос.УстановитьПараметр("ТЗ", ТаблицаОтбора);

Отбор по иерархии: В ИЕРАРХИИ со списком групп

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

bsl
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка В ИЕРАРХИИ(&Группы)";
Запрос.УстановитьПараметр("Группы", МассивГрупп);

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

Проверка результата и защита от пустого списка

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

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

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

Список заполнен и отбор обязателенПередавайте список в параметр и используйте условие В (&Список)
Список может оказаться пустым, а данные всё равно нужныПроверяйте Количество() перед установкой параметра и формируйте текст запроса без условия отбора
Пустой список означает «ничего не выбирать»Не выполняйте запрос вовсе — сразу возвращайте пустой результат, экономя время сервера
Список содержит тысячи элементовИспользуйте таблицу значений через временную таблицу вместо условия В
Контрольные точки

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

Количество строк результата
Норма

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

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

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

Тип значений в списке
Норма

Все элементы списка — ссылки того же типа, что и поле отбора

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

В списке смешаны ссылки разных типов или строки — часть значений молча не сработает

Дубликаты
Норма

Дубли в списке не влияют на результат условия В

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

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

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

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

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

Третий момент — динамическое формирование текста запроса. Если условие добавляется в зависимости от заполненности списка, не собирайте текст конкатенацией с подстановкой значений пользователя — это риск ошибок и инъекций в текст запроса. Используйте параметры: платформа безопасно передаёт значения любого типа.

Типичные ошибки при работе со списком-параметром

Типичные ошибки
01
Передача пустого списка без проверки — запрос возвращает ноль строк, и это принимают за отсутствие данных в базе.
02
Пропущенные скобки: условие записано как В &Список вместо В (&Список) — синтаксическая ошибка при выполнении.
03
Смешение типов в списке: ссылки разных справочников или строки вместо ссылок — часть значений молча не участвует в отборе.
04
Передача таблицы значений напрямую в условие В — таблица так не работает, её нужно помещать во временную таблицу.
05
Использование В ИЕРАРХИИ для неиерархического объекта — запрос падает с ошибкой.
06
Дубли во временной таблице отбора при соединении — строки результата задваиваются, что искажает итоги.

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

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

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

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

Что быстрее: условие В со списком или временная таблица?

Для небольших списков (десятки — сотни значений) разницы практически нет. Для тысяч и десятков тысяч элементов временная таблица с соединением обычно работает быстрее и стабильнее, особенно в клиент-серверном варианте.

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

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

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

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

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

Да. В параметрах виртуальных таблиц (например, Остатки) условие записывается прямо в скобках: Остатки(, Номенклатура В (&Список)). Это эффективнее, чем фильтровать результат в секции ГДЕ, потому что отбор выполняется на уровне СУБД до формирования выборки.

Что делать, если список формируется пользователем и его размер не ограничен?

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

Итог

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

Список передаётся в запрос через УстановитьПараметр и условие В (&Имя) — подходят массив и список значений. Для иерархии используйте В ИЕРАРХИИ, для больших объёмов и составного отбора — таблицу значений через временную таблицу. Всегда проверяйте список на пустоту и соответствие типов перед выполнением запроса.