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