Параметры запроса 1С 8.3: от УстановитьПараметр до СКД и динамических списков
Содержание
Параметр в запросе 1С объявляют в тексте символом & перед именем (&Организация), а значение передают из кода методом Запрос.УстановитьПараметр("Организация", Значение) до вызова Выполнить(). Имя в тексте и в методе должно совпадать, регистр букв роли не играет.
Дальше всё упирается в детали. Как передать список вместо одного значения, почему отчёт за день теряет вечерние документы, где задать параметр в СКД и в динамическом списке формы. Ниже — рабочие примеры для платформы 8.3 и типовые ошибки, на которых спотыкаются даже опытные разработчики.
Как объявить параметр в тексте запроса и передать значение
Схема одна для любого объекта Запрос: текст с метками &Имя → установка значений → выполнение.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Контрагенты.Ссылка КАК Ссылка,
| Контрагенты.ИНН КАК ИНН
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| Контрагенты.ИНН = &ИНН
| И НЕ Контрагенты.ПометкаУдаления";
Запрос.УстановитьПараметр("ИНН", "7701234567");
Выборка = Запрос.Выполнить().Выбрать();
Что стоит знать про синтаксис:
- 🔹 Имя параметра — как имя переменной: буквы, цифры, подчёркивание, без пробелов. Начинаться с цифры не может.
- 🔹 Один параметр можно использовать в тексте сколько угодно раз. Значение устанавливается один раз.
- 🔹 Параметр работает в
ГДЕ,ИМЕЮЩИЕ, в условиях соединения, в полях выборки и в параметрах виртуальных таблиц. - 🔹 Тип значения не объявляется заранее. Платформа берёт его из того, что передали: строка, число, дата, булево, ссылка,
Неопределено.
Второй способ: коллекция Параметры
У объекта Запрос есть свойство Параметры — это структура. Запись Запрос.Параметры.Вставить("ИНН", "7701234567") даёт тот же результат, что и УстановитьПараметр. Удобно, когда параметры готовят заранее одной структурой и передают в общий модуль.
Метод Запрос.НайтиПараметры() возвращает описание всех параметров, которые есть в тексте. Его используют в универсальных обработках: пробегают по коллекции и проверяют, что каждому параметру задано значение.
Чем параметр лучше склейки строк
Начинающие иногда пишут условие так: "ГДЕ Контрагенты.ИНН = """ + ИНН + """". Работать будет до первой кавычки в данных или до даты, которую платформа приведёт к строке в своём формате.
| Подход | Типизация | Кавычки и спецсимволы | Читаемость |
|---|---|---|---|
Параметр &ИНН | значение уходит с типом | не мешают | текст запроса не меняется |
| Склейка строк | всё превращается в строку | ломают запрос | текст собирается по кускам |
Ссылку на элемент справочника через склейку не передать вовсе. Через параметр — одной строкой.
Значения, которые не нужно передавать параметром
Часть констант удобнее записать прямо в тексте функцией ЗНАЧЕНИЕ(). Так запрос короче, а в коде меньше лишних вызовов.
ГДЕ
Документ.ВидОперации = ЗНАЧЕНИЕ(Перечисление.ВидыОперацийПоступлениеТоваровУслуг.Товары)
И Документ.Контрагент <> ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)
Через ЗНАЧЕНИЕ() записывают значения перечислений, предопределённые элементы справочников и планов счетов, пустые ссылки. Имя перечисления в примере условное: подставьте то, что есть в вашей конфигурации.
А вот что параметром передать нельзя:
- ⛔ Имя таблицы или поля. Запрос
ВЫБРАТЬ * ИЗ &ИмяТаблицыне заработает. Если таблица выбирается динамически, текст собирают черезСтрЗаменить()по заранее известному списку имён. - ⛔ Число в
ПЕРВЫЕ N. Там допустима только константа в тексте. - ⛔ Направление сортировки и ключевые слова языка запросов.
Передаём список значений в условие В
Чтобы отобрать сразу несколько контрагентов, складов или документов, в тексте пишут В (&Список), а в параметр передают коллекцию.
Запрос.Текст =
"ВЫБРАТЬ
| Остатки.Номенклатура,
| Остатки.КоличествоОстаток
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(, Склад В (&Склады)) КАК Остатки";
Склады = Новый Массив;
Склады.Добавить(Справочники.Склады.НайтиПоНаименованию("Основной склад"));
Склады.Добавить(Справочники.Склады.НайтиПоНаименованию("Розница"));
Запрос.УстановитьПараметр("Склады", Склады);
Имя регистра и его измерения в примере условные — подставьте свои.
Какие коллекции принимает условие В:
| Что передаём | Когда удобно |
|---|---|
Массив | собрали ссылки в цикле или получили ВыгрузитьКолонку() |
СписокЗначений | значения пришли из формы или из отбора пользователя |
ФиксированныйМассив | значения из параметров сеанса или повторно используемого модуля |
Пустой массив — частая ловушка. В (&Список) с пустой коллекцией не вызывает ошибку, а просто возвращает ноль строк. Если по задумке пустой список означает «без отбора», проверьте это в коде и уберите условие из текста заранее.
Таблица значений как параметр
Параметром можно передать целую таблицу значений и сразу положить её во временную таблицу. Это главный приём, когда нужно соединить данные из памяти с данными базы.
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
ТЗ.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)));
// ... заполнение строк ...
Запрос.Текст =
"ВЫБРАТЬ
| Т.Номенклатура КАК Номенклатура,
| Т.Количество КАК Количество
|ПОМЕСТИТЬ ВТ_Данные
|ИЗ
| &ТЗ КАК Т";
Запрос.УстановитьПараметр("ТЗ", ТЗ);
Колонки таблицы значений обязательно типизируйте через ОписаниеТипов. Колонка без типа не пройдёт в запрос, и платформа выдаст ошибку о неподдерживаемом типе. Выбирать из параметра-таблицы можно только с помещением во временную таблицу, как в примере.
Параметры с датой: где теряются документы последнего дня
Дата в 1С всегда хранит время. Если пользователь выбрал период с 1 по 31 октября, в переменной окажется 31.10.2026 0:00:00. Документ, проведённый 31-го в 15:20, в условие Дата <= &КонецПериода уже не попадёт.
Два способа это исправить:
- В коде:
Запрос.УстановитьПараметр("КонецПериода", КонецДня(ДатаОкончания)). - В тексте запроса:
Документ.Дата МЕЖДУ НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ) И КОНЕЦПЕРИОДА(&КонецПериода, ДЕНЬ).
Второй вариант надёжнее: запрос остаётся корректным, даже если его вызовет другой код без КонецДня(). Функции НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА принимают периоды ДЕНЬ, НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД и другие.
Остатки на дату и объект Граница
Виртуальная таблица остатков с параметром-датой показывает состояние на начало этого момента. Движения документа, у которого дата и время совпадают с переданными, в результат не входят.
Чтобы включить их, передают не дату, а границу:
Запрос.УстановитьПараметр("Период",
Новый Граница(КонецДня(ДатаОстатков), ВидГраницы.Включая));
А чтобы получить остатки строго перед проведением конкретного документа (типичная задача при контроле в модуле проведения), передают его момент времени:
Запрос.УстановитьПараметр("Период",
Новый Граница(Документ.МоментВремени(), ВидГраницы.Исключая));
В тексте запроса при этом пишут обычное .Остатки(&Период, ...) — тип значения платформа поймёт сама.
| Что передали в &Период | Какие движения попадут |
|---|---|
Дата 31.10.2026 0:00:00 | только до начала этой секунды |
Граница(КонецДня(...), Включая) | все движения за 31 октября |
Граница(МоментВремени(), Исключая) | всё, что было до этого документа |
Параметры в схеме компоновки данных
В отчётах на СКД параметры появляются автоматически. Написали в наборе данных &Организация — на вкладке Параметры схемы возникла строка с этим именем.
Что настраивают у параметра на этой вкладке:
- 📌 Заголовок — как параметр подписан в настройках отчёта.
- 📌 Тип — без явного типа пользователь не сможет выбрать значение из справочника.
- 📌 Доступен список значений — разрешает выбрать несколько значений для условия
В. - 📌 Выражение — значение вычисляется из других параметров.
- 📌 Ограничение доступности — параметр скрыт от пользователя, значение задаёт разработчик.
Период через СтандартныйПериод
Классический приём для отчёта за период. В тексте запроса используют &НачалоПериода и &КонецПериода. На вкладке Параметры добавляют ещё один параметр Период с типом СтандартныйПериод.
Дальше у служебных параметров заполняют поле «Выражение»:
- у
НачалоПериода—&Период.ДатаНачала; - у
КонецПериода—&Период.ДатаОкончания.
Им же ставят флажок ограничения доступности. Пользователь видит одно привычное поле выбора периода с вариантами «Этот месяц», «Прошлый квартал» и так далее. ДатаОкончания у стандартного периода уже указывает на конец дня, так что проблема потерянного последнего дня здесь не возникает.
Как вывести параметр в шапку отчёта
Чтобы параметр отображался над таблицей, а не прятался в настройках, откройте в редакторе схемы вкладку Настройки. В нижней части выберите закладку Параметры, отметьте нужный параметр флажком и откройте его свойства элемента пользовательских настроек. Там укажите режим отображения «Быстрый доступ».
Установка параметра СКД из кода
Если отчёт формируется программно или значение нужно подставить при открытии формы, обращаются к настройкам компоновщика:
Настройки = КомпоновщикНастроек.Настройки;
Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("Организация", Организация);
Когда параметр включён в пользовательские настройки, значение надо менять ещё и в КомпоновщикНастроек.ПользовательскиеНастройки. Иначе при формировании пользовательская настройка перекроет то, что вы установили в основных.
Параметры динамического списка на форме
Динамический список с произвольным запросом тоже принимает параметры. Включите у реквизита формы флажок «Произвольный запрос», напишите в тексте &Владелец и установите значение в модуле формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Список.Параметры.УстановитьЗначениеПараметра("Владелец", Параметры.Владелец);
КонецПроцедуры
Если параметр меняется в процессе работы (пользователь выбрал другую организацию в поле над списком), вызывайте УстановитьЗначениеПараметра в обработчике ПриИзменении этого поля. Список перечитается сам.
Параметр, которому не задали значение, — частая причина пустого списка при открытии формы. Устанавливайте все параметры уже в ПриСозданииНаСервере, хотя бы пустыми ссылками нужного типа.
Параметры и скорость запроса
Сам факт использования параметра на скорость не влияет. Влияет то, где стоит условие.
Отбор переносите в параметры виртуальной таблицы. Сравните два варианта:
// Медленно: сначала считаются остатки по всем складам, потом отсекаются лишние
ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки(&Период) КАК Остатки
ГДЕ Остатки.Склад = &Склад
// Быстро: отбор применяется ещё при расчёте остатков
ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Склад = &Склад) КАК Остатки
На небольшой базе разница незаметна. На регистре с миллионами записей — это секунды против минут.
Ещё несколько правил:
- 🚀 Длинный список в условии В (сотни и тысячи значений) лучше передать таблицей значений, поместить во временную таблицу и соединиться с ней. Индексируйте её:
ИНДЕКСИРОВАТЬ ПО Номенклатура. - 🚀 Не вызывайте запрос в цикле с новым значением параметра на каждой итерации. Соберите все значения в массив и выполните один запрос с
В (&Список). - 🚀 Не оборачивайте поле функцией ради сравнения с параметром.
НАЧАЛОПЕРИОДА(Документ.Дата, ДЕНЬ) = &Датане даёт использовать индекс по дате. УсловиеДокумент.Дата МЕЖДУ &Начало И &Конецдаёт. - 🚀 Пакетный запрос с временными таблицами использует одни и те же параметры во всех запросах пакета. Устанавливать их повторно не нужно.
Ошибки при установке параметров и как их найти
Большинство проблем с параметрами не вызывают сообщения об ошибке. Запрос выполняется, но возвращает не то. Проверить себя помогает консоль запросов: в ней значения параметров задают вручную в отдельной таблице и сразу видят результат.
Регистр букв и составные типы
Регистр в имени параметра не важен: &ОРГАНИЗАЦИЯ и УстановитьПараметр("Организация", ...) найдут друг друга. А вот тип важен всегда.
Если поле составного типа (например, регистратор), а вы сравниваете его с параметром-ссылкой, платформа сравнит корректно. Но если передать в такое условие Неопределено, получите только записи с пустым значением, а не «любые». Для отключения отбора нужен отдельный вариант текста запроса.