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