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