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