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