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