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

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

Массив в запросе 1С: как передать и использовать

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

В языке запросов 1С нет собственного типа «массив», но платформа позволяет передать массив (или список значений) в запрос как параметр и использовать его для фильтрации данных. Это один из самых частых приёмов при выборке документов по списку контрагентов, номенклатуры или складов. Без параметра-массива пришлось бы выполнять запрос в цикле, что резко увеличивает нагрузку на сервер.

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

Ниже разобраны оба подхода с примерами кода, ограничения платформы, типичные ошибки и способы проверить, что запрос работает корректно. Примеры ориентированы на управляемые формы и типовой синтаксис платформы 8.3.

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

Базовый механизм — метод УстановитьПараметр объекта Запрос. Платформа принимает в качестве значения параметра массив, список значений или таблицу значений. В тексте запроса параметр указывается с амперсандом, а условие строится через оператор В:

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

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

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

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

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

"ВЫБРАТЬ

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

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

|ИЗ

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

|ГДЕ

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

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

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

Важно, чтобы элементы массива имели тип, совместимый с типом поля в условии. Если поле «Контрагент» — ссылка на справочник «Контрагенты», то в массиве должны быть именно ссылки этого справочника. Смешение типов (например, ссылка и строка с наименованием) приведёт к тому, что часть значений не сработает в отборе без какого-либо сообщения об ошибке.

Отбор по массиву: условие В и В ИЕРАРХИИ

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

|ГДЕ

| Номенклатура.Родитель В ИЕРАРХИИ(&МассивГрупп)

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

Обратный отбор строится через НЕ В:

|ГДЕ

| НЕ Документ.Склад В (&ИсключаемыеСклады)

Учтите, что конструкция НЕ В чувствительна к значениям NULL: если поле может быть не заполнено, результат может отличаться от ожидаемого. В таких случаях добавляйте проверку ИЛИ Поле ЕСТЬ NULL в зависимости от требуемой логики.

Помещение массива во временную таблицу

Когда массив нужно не только для фильтрации, но и для соединения с другими данными, его помещают во временную таблицу. Это делается через конструкцию ВЫБРАТЬ ... ПОМЕСТИТЬ с параметром-массивом:

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

"ВЫБРАТЬ

| Список.Значение КАК Контрагент

|ПОМЕСТИТЬ ВТ_Контрагенты

|ИЗ

| &СписокКонтрагентов КАК Список

|;

|ВЫБРАТЬ

| Долги.Контрагент,

| СУММА(Долги.СуммаОстаток) КАК Долг

|ИЗ

| РегистрНакопления.Взаиморасчеты.Остатки КАК Долги

| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Контрагенты КАК ВТ

| ПО Долги.Контрагент = ВТ.Контрагент

|СГРУППИРОВАТЬ ПО

| Долги.Контрагент";

Для такого подхода параметром передаётся не простой массив, а таблица значений с именованной колонкой. Таблицу готовят в коде:

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

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

Для Каждого Элемент Из МассивКонтрагентов Цикл

Строка = ТЗ.Добавить();

Строка.Значение = Элемент;

КонецЦикла;

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

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

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

Массив в параметрах виртуальных таблиц

Тот же приём работает в параметрах виртуальных таблиц регистров. Например, для отбора остатков по списку складов:

|ИЗ

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

| ,

| Склад В (&МассивСкладов)

| И Номенклатура В (&МассивНоменклатуры)) КАК Остатки

Отбор в параметрах виртуальной таблицы выполняется до формирования выборки, поэтому он эффективнее, чем аналогичное условие в секции ГДЕ. Это особенно заметно на больших регистрах: сервер СУБД читает только нужные записи, а не весь регистр с последующей фильтрацией.

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

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

Первая частая ошибка — пустой массив. Условие Поле В (&ПустойМассив) не вернёт ни одной строки, и это не всегда очевидно разработчику. Если пустой список должен означать «без отбора», добавляйте ветвление: либо формируйте другой текст запроса, либо используйте конструкцию вида ГДЕ (&ЕстьОтбор = ЛОЖЬ ИЛИ Поле В (&Массив)).

Вторая ошибка — дубли в массиве. При соединении через временную таблицу дубликаты значений приводят к задвоению строк результата. Перед передачей очищайте массив от повторов (например, через соответствие) или применяйте РАЗЛИЧНЫЕ при помещении во временную таблицу.

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

Типичные ошибки
01
Пустой массив в условии В — запрос возвращает ноль строк, причина неочевидна
02
Дубликаты значений при соединении с временной таблицей — задвоение строк результата
03
Несовпадение типов элементов массива и поля отбора — отбор молча не срабатывает
04
Передача огромного массива напрямую в условие В — деградация производительности запроса

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

Быстрый способ отладки — выгрузить результат в таблицу значений и посмотреть её через метод ВыбратьСтроку() в толстом клиенте или вывести количество строк в сообщение:

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

Сообщить("Строк в результате: " + РезультатТЗ.Количество());

Дополнительно убедитесь, что параметр дошёл до запроса корректно: перед выполнением проверьте Массив.Количество() и тип первого элемента через ТипЗнч(). Если запрос возвращает пустой результат, первым делом смотрите на эти два значения — в большинстве случаев причина именно в них.

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

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

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

Количество элементов массива перед запросом
Норма

Количество соответствует ожидаемому списку отбора

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

Массив пуст или содержит лишние элементы

Тип элементов массива
Норма

Тип совпадает с типом поля в условии

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

Строки или числа вместо ссылок

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

Строки соответствуют отобранным значениям без дублей

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

Пустой результат или задвоенные строки

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

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

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

Что будет, если передать в условие В пустой массив?

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

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

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

Как отобрать по нескольким парам значений, например контрагент + договор?

Один массив для пары значений не подходит. Создайте таблицу значений с двумя колонками, поместите её во временную таблицу и соедините с основными данными по обоим полям одновременно.

Чем условие В отличается от соединения с временной таблицей?

Условие В только фильтрует результат по списку значений. Соединение с временной таблицей дополнительно позволяет передавать несколько полей на элемент, получать строки для отсутствующих в основной таблице значений (через левое соединение) и строить более сложную логику.

Итог

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

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