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