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

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

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

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

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

Все параметры в тексте запроса обозначаются символом амперсанда: &Период, &Контрагент, &СписокТоваров. Значения им присваиваются через метод УстановитьПараметр() объекта «Запрос» до вызова Выполнить() или ВыполнитьПакет(). Если параметр объявлен в тексте, но не установлен, платформа выдаст ошибку «Переменная не определена».

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

Базовый синтаксис: УстановитьПараметр

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

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

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

"ВЫБРАТЬ

| Номенклатура.Ссылка КАК Товар,

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

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

| Номенклатура.Родитель = &Группа";

Запрос.УстановитьПараметр("Группа", ВыбраннаяГруппа);

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

Имя параметра в УстановитьПараметр() пишется без амперсанда и без учёта регистра. Порядок установки параметров относительно друг друга не важен — важно только, чтобы все они были заданы до выполнения. Один и тот же параметр можно использовать в тексте несколько раз, устанавливать его нужно один раз.

Повторный вызов УстановитьПараметр() с тем же именем перезаписывает значение. Это удобно в циклах: текст запроса остаётся неизменным, меняется только параметр, и СУБД может повторно использовать уже построенный план запроса.

Передача дат и периодов

Даты передаются как значения типа «Дата», а не как строки. Частая ошибка — сформировать строку вида «20260101» и передать её в параметр: сравнение даты со строкой либо даст ошибку, либо вернёт пустой результат в зависимости от СУБД.

Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ДатаНачала));

Запрос.УстановитьПараметр("КонецПериода", КонецДня(ДатаОкончания));

Для отбора документов за период используйте границы МЕЖДУ &НачалоПериода И &КонецПериода или сравнения >= и <=. Помните, что у даты в 1С есть время: если передать дату окончания без времени, она будет равна началу дня, и документы за сам день окончания не попадут в выборку. Поэтому применяйте КонецДня().

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

Передача списков и массивов

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

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

"ВЫБРАТЬ

| Товары.Ссылка КАК Товар

|ИЗ

| Справочник.Номенклатура КАК Товары

|ГДЕ

| Товары.Ссылка В (&СписокТоваров)";

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

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

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

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

Передача таблицы значений как параметра

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

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

"ВЫБРАТЬ

| ТЗ.Товар КАК Товар,

| ТЗ.Количество КАК Количество

|ПОМЕСТИТЬ ВТ_Товары

|ИЗ

| &ТЗ КАК ТЗ

|;

|ВЫБРАТЬ

| ВТ.Товар КАК Товар,

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

|ИЗ

| ВТ_Товары КАК ВТ

| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки

| ПО ВТ.Товар = Остатки.Номенклатура";

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

Требования к таблице значений: колонки должны быть типизированы, причём типы должны совпадать с типами полей, с которыми они сравниваются. Если колонка «Товар» имеет составной тип или не заполнен тип вовсе, соединение может вернуть пустой результат. Для временных таблиц в пакетном запросе потребуется менеджер временных таблиц при передаче между запросами, либо пакет внутри одного объекта запроса, как в примере выше.

Параметры виртуальных таблиц регистров

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

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

"ВЫБРАТЬ

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

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

|ИЗ

| РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Склад = &Склад) КАК Остатки";

Запрос.УстановитьПараметр("Период", КонецДня(ДатаОстатков));

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

Для «СрезПоследних» и «СрезПервых» первый параметр — период, второй — условие отбора по измерениям. Если период не нужен (актуальный срез), скобки оставляют пустыми: СрезПоследних(, Номенклатура = &Товар). Отбор в скобках виртуальной таблицы почти всегда эффективнее аналогичного условия в ГДЕ, потому что СУБД читает меньше данных.

Конструкция «В (&Параметр)» против соединения с временной таблицей

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

КритерийМассив в В (&Параметр)Временная таблица из ТЗ
Размер набораДесятки–сотни значенийТысячи строк и больше
СтруктураОдно значение (ссылка, код)Несколько колонок, составной ключ
Дополнительные данныеНе передаютсяМожно тащить колонки (количество, цена)
ПодготовкаМинимальнаяНужна типизированная таблица значений

Для составных условий (товар + склад + характеристика) массив не подходит в принципе — только временная таблица с соединением по всем полям. Для простого отбора по десятку контрагентов массив проще и читаемее.

Сравнение вариантов

Массив в операторе В

Подходит для небольших списков однотипных значений. Ограничение: одно поле сравнения, при большом объёме ухудшает план запроса

Таблица значений во временную таблицу

Подходит для больших наборов и составных ключей, позволяет передать дополнительные колонки. Ограничение: требует типизации колонок и больше кода

Отбор в параметрах виртуальной таблицы

Самый быстрый вариант для регистров: фильтрация до чтения данных. Ограничение: работает только с измерениями и периодом виртуальной таблицы

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

Если запрос с параметрами возвращает пустой результат, проверяйте в первую очередь типы и значения параметров. Выведите их в отладчике: ТипЗнч(Значение) и само значение. Убедитесь, что ссылка относится к тому же типу, что и поле сравнения, — ссылка на «Номенклатуру» никогда не равна ссылке на «Партнёра», даже если наименования совпадают.

Для отладки удобно временно убрать условие и посмотреть, есть ли вообще данные в таблице, затем возвращать условия по одному. Так локализуется параметр, который «режет» выборку. Полезно также выполнить запрос в консоли запросов с теми же значениями параметров — это отделяет проблему данных от проблемы кода.

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

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

Тип параметра
Норма

ТипЗнч() даёт тот же тип, что у поля сравнения (например, СправочникСсылка.Номенклатура)

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

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

Значение даты-границы
Норма

Конец периода содержит время 23:59:59 или используется КонецДня()

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

Время 00:00:00 — документы последнего дня не попадают

Список для оператора В
Норма

Массив заполнен, элементы нужного типа

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

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

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

Запрос выполняется без исключений, Выборка.Следующий() находит строки

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

Ошибка «Переменная не определена» — параметр не установлен

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

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

Технически можно, но делать так не стоит. Подстановка строк ломает кэширование плана запроса на СУБД, создаёт риск синтаксических ошибок на спецсимволах и делает код уязвимым при передаче пользовательского ввода. Используйте УстановитьПараметр для всех значений.

Как передать в запрос значение NULL?

Передайте значение Неопределено — платформа преобразует его в NULL. В тексте запроса проверяйте через «ЕСТЬ NULL» или сравнение «= &Параметр» в зависимости от логики. Помните, что сравнение с NULL через равенство не срабатывает: используйте конструкцию «Поле ЕСТЬ NULL».

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

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

Почему запрос с параметром-таблицей значений возвращает пустой результат?

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

Как передать параметр в динамический список, а не в объект Запрос?

У динамического списка параметры устанавливаются через коллекцию Параметры: ДинамическийСписок.Параметры.УстановитьЗначениеПараметра("Период", Дата). В тексте произвольного запроса динамического списка параметр обозначается тем же амперсандом.

Итог

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

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