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

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

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

Как передать массив или список значений в запрос 1С как параметр: УстановитьПараметр, В(&Массив), проверка на пустоту, типичные ошибки и примеры кода.

Передача массива в запрос — одна из самых частых задач при разработке на платформе 1С:Предприятие. Типичный сценарий: у вас есть список номенклатуры, контрагентов или документов, и нужно одним запросом получить по ним данные вместо того, чтобы выполнять запрос в цикле. Язык запросов 1С поддерживает это напрямую: массив передаётся через метод УстановитьПараметр() и используется в условии В (&ИмяПараметра).

Главное, что нужно понять сразу: параметр с массивом работает только в операторах сравнения со списком — В и НЕ В. Нельзя сравнивать поле с массивом через обычное равенство — запрос упадёт с ошибкой или вернёт неправильный результат. Также важно помнить про ограничение СУБД на количество элементов в условии IN: при очень больших массивах запрос может стать медленным или вообще не выполниться.

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

Базовый пример: массив в условии В (&Параметр)

Минимальный рабочий пример выглядит так. Сначала формируется массив ссылок, затем он устанавливается как параметр запроса, а в тексте запроса поле сравнивается с параметром через оператор В.

МассивНоменклатуры = Новый Массив;

МассивНоменклатуры.Добавить(СсылкаТовар1);

МассивНоменклатуры.Добавить(СсылкаТовар2);

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

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

"ВЫБРАТЬ

| Остатки.Номенклатура КАК Номенклатура,

| Остатки.КоличествоОстаток КАК Остаток

|ИЗ

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

| ,

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

Запрос.УстановитьПараметр("МассивНоменклатуры", МассивНоменклатуры);

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

Обратите внимание: параметр устанавливается один раз, до выполнения запроса. Имя параметра в УстановитьПараметр() пишется без амперсанда, а в тексте запроса — с амперсандом. Это частая причина ошибки «Параметр не найден» у начинающих разработчиков.

Оператор В работает и в секции ГДЕ, и в параметрах виртуальных таблиц, как в примере выше. Передача отбора в параметры виртуальной таблицы обычно эффективнее, потому что СУБД отфильтрует данные на раннем этапе, до соединений и группировок.

bsl
Запрос.УстановитьПараметр("СписокКонтрагентов", МассивКонтрагентов); // в тексте запроса: ГДЕ Контрагент В (&СписокКонтрагентов)

Какие типы можно передавать: массив, список значений, таблица значений

Платформа принимает в качестве параметра для оператора В не только массив. Поддерживаются также СписокЗначений и ТаблицаЗначений. Для таблицы значений используется конструкция В (&Таблица) либо отдельная временная таблица — это разные механизмы с разной производительностью.

Если данные уже лежат в таблице значений (например, загружены из файла или получены из другого запроса), передавать её напрямую в В (&Таблица) неудобно: платформа возьмёт первую колонку, что не всегда очевидно. Надёжнее выгрузить колонку в массив методом ВыгрузитьКолонку("ИмяКолонки") и передать уже массив.

Для больших объёмов данных (тысячи и десятки тысяч строк) вместо массива лучше использовать временную таблицу через менеджер временных таблиц: таблица помещается во временное хранилище СУБД и соединяется с основными данными обычным СОЕДИНЕНИЕ. Это снимает ограничение на длину списка в IN и работает заметно быстрее на больших объёмах.

Способы передать набор значений в запрос

Массив

До нескольких сотен элементов. Простой код, передаётся прямо в УстановитьПараметр. На больших объёмах замедляет запрос.

Список значений

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

Временная таблица

Тысячи и более элементов, нужны дополнительные поля для соединения. Требует МенеджерВременныхТаблиц и больше кода.

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

Если передать в запрос пустой массив, условие В (&Массив) не выполнится ни для одной строки — запрос просто вернёт пустой результат. Ошибки не будет, и это коварно: логика программы может молча работать неправильно, и вы долго не заметите проблему.

Поэтому перед установкой параметра стоит явно проверить наполненность массива и решить, как должна вести себя программа: не выполнять запрос вовсе, вернуть пустую таблицу или, наоборот, выбрать все данные без отбора. Третий вариант реализуется через условие ГДЕ (&МассивПуст ИЛИ Номенклатура В (&Массив)) с дополнительным булевым параметром.

Если МассивНоменклатуры.Количество() = 0 Тогда

Возврат Новый ТаблицаЗначений; // или иная логика

КонецЕсли;

Отбор по нескольким полям и вложенные условия

Массивов в одном запросе может быть несколько — например, отбор одновременно по списку складов и списку номенклатуры. Каждый массив передаётся отдельным параметром и используется в своём условии В.

Если нужен отбор по паре «поле1 + поле2» (например, конкретные комбинации номенклатуры и склада), один массив не поможет. Здесь два пути: либо два массива с условием В по каждому (но это даст декартово произведение пар, что не всегда корректно), либо временная таблица с двумя колонками и соединение по обоим полям — это точный и производительный вариант.

Также массивы применяются в иерархических отборах: В ИЕРАРХИИ (&Группы), где параметр — массив групп справочника. Это позволяет одним запросом выбрать элементы из нескольких веток дерева.

Запрос.УстановитьПараметр("Склады", МассивСкладов);

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

// В тексте: ГДЕ Склад В (&Склады) И Номенклатура В (&Товары)

Массив в СКД и динамических списках

В схеме компоновки данных массивы передаются через параметры настроек. В тексте запроса СКД параметр объявляется как обычно, а в настройках отчёта ему присваивается список значений — пользователь может выбрать несколько элементов прямо в форме отчёта. В коде это делается через КомпоновщикНастроек: найти параметр по имени и установить значение типа СписокЗначений.

Важный нюанс СКД: если в тексте запроса условие написано явно в секции ГДЕ, оно становится жёстким и всегда обязательным. Чтобы отбор по списку можно было включать и отключать в настройках, условие лучше убирать из текста запроса и добавлять его через отбор компоновки, либо использовать фигурные скобки расширения языка запросов СКД.

Порядок передачи массива в запрос
  1. 1
    Сформируйте массив нужных ссылок или значений
  2. 2
    Проверьте, что массив не пуст (Количество() > 0)
  3. 3
    Создайте объект Запрос и задайте текст с условием В (&ИмяПараметра)
  4. 4
    Вызовите Запрос.УстановитьПараметр("ИмяПараметра", Массив)
  5. 5
    Выполните запрос и проверьте результат на пустоту

Типичные ошибки и как их диагностировать

Самая частая ошибка — несовпадение типов: в массиве лежат строки с кодами, а поле в запросе имеет тип «Число» или ссылку. Условие В в этом случае молча не срабатывает. Всегда проверяйте, что тип элементов массива совпадает с типом поля, с которым идёт сравнение.

Вторая группа ошибок — синтаксические: амперсанд в имени параметра при вызове УстановитьПараметр, отсутствие амперсанда в тексте запроса, сравнение через равенство вместо В. Такие ошибки платформа отловит при выполнении с понятным сообщением.

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

Типичные ошибки
01
Сравнение поля с массивом через равенство (= &Массив) вместо В — запрос падает или работает неверно
02
Передача массива с элементами другого типа, чем поле — условие молча не срабатывает
03
Отсутствие проверки на пустой массив — пустой результат без какой-либо ошибки
04
Амперсанд в имени параметра при вызове УстановитьПараметр — ошибка «параметр не найден»
05
Передача огромного массива вместо временной таблицы — тайм-ауты и деградация производительности

Проверка результата и отладка

Быстрый способ убедиться, что параметр дошёл до запроса, — выполнить тот же запрос в консоли запросов (в режиме предприятия или через внешний инструмент) с тем же массивом и сравнить результат. Если в консоли данные есть, а в коде нет — проблема в установке параметра или в типе элементов.

Для отладки полезно вывести количество элементов массива и тип первого элемента через Сообщить() или журнал регистрации: ТипЗнч(Массив[0]) сразу покажет несоответствие типов. Также проверьте, не содержит ли массив пустых ссылок или Неопределено — они не ломают запрос, но искажают результат.

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

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

Количество строк результата
Норма

Больше нуля при непустом массиве и существующих данных

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

Ноль строк — проверьте типы элементов и наполненность массива

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

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

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

Строки вместо ссылок, Неопределено, пустые ссылки

Время выполнения
Норма

Запрос выполняется за приемлемое время

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

Тайм-ауты при большом массиве — переходите на временную таблицу

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

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

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

Что будет, если массив содержит значение Неопределено?

Запрос выполнится без ошибки, но значение Неопределено не сравнится ни с одним значением поля. Рекомендуется очищать массив от Неопределено и пустых ссылок перед передачей, чтобы результат был предсказуемым.

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

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

Можно ли передать массив в запрос через консоль кода на управляемых формах?

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

Как передать массив как параметр виртуальной таблицы регистра?

Точно так же, как в обычное условие ГДЕ: в параметрах виртуальной таблицы укажите условие вида Номенклатура В (&Массив), а сам массив установите через УстановитьПараметр. Это предпочтительный вариант, так как отбор применяется до основной выборки.

Чем отличается передача списка значений от массива?

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

Итог

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

Массив передаётся в запрос через УстановитьПараметр и используется только с оператором В. Проверяйте массив на пустоту и соответствие типов элементов полю отбора. Для больших объёмов и отборов по нескольким полям используйте временные таблицы вместо массива.