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