Параметры запроса 1С 8.3: от УстановитьПараметр до СКД и динамических списков

· 9 мин

Содержание

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

Дальше всё упирается в детали. Как передать список вместо одного значения, почему отчёт за день теряет вечерние документы, где задать параметр в СКД и в динамическом списке формы. Ниже — рабочие примеры для платформы 8.3 и типовые ошибки, на которых спотыкаются даже опытные разработчики.

Как объявить параметр в тексте запроса и передать значение

Схема одна для любого объекта Запрос: текст с метками &Имя → установка значений → выполнение.

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
|	Контрагенты.Ссылка КАК Ссылка,
|	Контрагенты.ИНН КАК ИНН
|ИЗ
|	Справочник.Контрагенты КАК Контрагенты
|ГДЕ
|	Контрагенты.ИНН = &ИНН
|	И НЕ Контрагенты.ПометкаУдаления";

Запрос.УстановитьПараметр("ИНН", "7701234567");
Выборка = Запрос.Выполнить().Выбрать();

Что стоит знать про синтаксис:

  • 🔹 Имя параметра — как имя переменной: буквы, цифры, подчёркивание, без пробелов. Начинаться с цифры не может.
  • 🔹 Один параметр можно использовать в тексте сколько угодно раз. Значение устанавливается один раз.
  • 🔹 Параметр работает в ГДЕ, ИМЕЮЩИЕ, в условиях соединения, в полях выборки и в параметрах виртуальных таблиц.
  • 🔹 Тип значения не объявляется заранее. Платформа берёт его из того, что передали: строка, число, дата, булево, ссылка, Неопределено.

Второй способ: коллекция Параметры

У объекта Запрос есть свойство Параметры — это структура. Запись Запрос.Параметры.Вставить("ИНН", "7701234567") даёт тот же результат, что и УстановитьПараметр. Удобно, когда параметры готовят заранее одной структурой и передают в общий модуль.

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

Чем параметр лучше склейки строк

Начинающие иногда пишут условие так: "ГДЕ Контрагенты.ИНН = """ + ИНН + """". Работать будет до первой кавычки в данных или до даты, которую платформа приведёт к строке в своём формате.

ПодходТипизацияКавычки и спецсимволыЧитаемость
Параметр &ИННзначение уходит с типомне мешаюттекст запроса не меняется
Склейка строквсё превращается в строкуломают запростекст собирается по кускам

Ссылку на элемент справочника через склейку не передать вовсе. Через параметр — одной строкой.

Значения, которые не нужно передавать параметром

Часть констант удобнее записать прямо в тексте функцией ЗНАЧЕНИЕ(). Так запрос короче, а в коде меньше лишних вызовов.

ГДЕ
	Документ.ВидОперации = ЗНАЧЕНИЕ(Перечисление.ВидыОперацийПоступлениеТоваровУслуг.Товары)
	И Документ.Контрагент <> ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)

Через ЗНАЧЕНИЕ() записывают значения перечислений, предопределённые элементы справочников и планов счетов, пустые ссылки. Имя перечисления в примере условное: подставьте то, что есть в вашей конфигурации.

А вот что параметром передать нельзя:

  • ⛔ Имя таблицы или поля. Запрос ВЫБРАТЬ * ИЗ &ИмяТаблицы не заработает. Если таблица выбирается динамически, текст собирают через СтрЗаменить() по заранее известному списку имён.
  • ⛔ Число в ПЕРВЫЕ N. Там допустима только константа в тексте.
  • ⛔ Направление сортировки и ключевые слова языка запросов.

Передаём список значений в условие В

Чтобы отобрать сразу несколько контрагентов, складов или документов, в тексте пишут В (&Список), а в параметр передают коллекцию.

Запрос.Текст =
"ВЫБРАТЬ
|	Остатки.Номенклатура,
|	Остатки.КоличествоОстаток
|ИЗ
|	РегистрНакопления.ТоварыНаСкладах.Остатки(, Склад В (&Склады)) КАК Остатки";

Склады = Новый Массив;
Склады.Добавить(Справочники.Склады.НайтиПоНаименованию("Основной склад"));
Склады.Добавить(Справочники.Склады.НайтиПоНаименованию("Розница"));
Запрос.УстановитьПараметр("Склады", Склады);

Имя регистра и его измерения в примере условные — подставьте свои.

Какие коллекции принимает условие В:

Что передаёмКогда удобно
Массивсобрали ссылки в цикле или получили ВыгрузитьКолонку()
СписокЗначенийзначения пришли из формы или из отбора пользователя
ФиксированныйМассивзначения из параметров сеанса или повторно используемого модуля

Пустой массив — частая ловушка. В (&Список) с пустой коллекцией не вызывает ошибку, а просто возвращает ноль строк. Если по задумке пустой список означает «без отбора», проверьте это в коде и уберите условие из текста заранее.

Таблица значений как параметр

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

ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
ТЗ.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)));
// ... заполнение строк ...

Запрос.Текст =
"ВЫБРАТЬ
|	Т.Номенклатура КАК Номенклатура,
|	Т.Количество КАК Количество
|ПОМЕСТИТЬ ВТ_Данные
|ИЗ
|	&ТЗ КАК Т";
Запрос.УстановитьПараметр("ТЗ", ТЗ);

Колонки таблицы значений обязательно типизируйте через ОписаниеТипов. Колонка без типа не пройдёт в запрос, и платформа выдаст ошибку о неподдерживаемом типе. Выбирать из параметра-таблицы можно только с помещением во временную таблицу, как в примере.

Параметры с датой: где теряются документы последнего дня

Дата в 1С всегда хранит время. Если пользователь выбрал период с 1 по 31 октября, в переменной окажется 31.10.2026 0:00:00. Документ, проведённый 31-го в 15:20, в условие Дата <= &КонецПериода уже не попадёт.

Два способа это исправить:

  1. В коде: Запрос.УстановитьПараметр("КонецПериода", КонецДня(ДатаОкончания)).
  2. В тексте запроса: Документ.Дата МЕЖДУ НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ) И КОНЕЦПЕРИОДА(&КонецПериода, ДЕНЬ).

Второй вариант надёжнее: запрос остаётся корректным, даже если его вызовет другой код без КонецДня(). Функции НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА принимают периоды ДЕНЬ, НЕДЕЛЯ, МЕСЯЦ, КВАРТАЛ, ГОД и другие.

Остатки на дату и объект Граница

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

Чтобы включить их, передают не дату, а границу:

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

А чтобы получить остатки строго перед проведением конкретного документа (типичная задача при контроле в модуле проведения), передают его момент времени:

Запрос.УстановитьПараметр("Период",
	Новый Граница(Документ.МоментВремени(), ВидГраницы.Исключая));

В тексте запроса при этом пишут обычное .Остатки(&Период, ...) — тип значения платформа поймёт сама.

Что передали в &ПериодКакие движения попадут
Дата 31.10.2026 0:00:00только до начала этой секунды
Граница(КонецДня(...), Включая)все движения за 31 октября
Граница(МоментВремени(), Исключая)всё, что было до этого документа

Параметры в схеме компоновки данных

В отчётах на СКД параметры появляются автоматически. Написали в наборе данных &Организация — на вкладке Параметры схемы возникла строка с этим именем.

Что настраивают у параметра на этой вкладке:

  • 📌 Заголовок — как параметр подписан в настройках отчёта.
  • 📌 Тип — без явного типа пользователь не сможет выбрать значение из справочника.
  • 📌 Доступен список значений — разрешает выбрать несколько значений для условия В.
  • 📌 Выражение — значение вычисляется из других параметров.
  • 📌 Ограничение доступности — параметр скрыт от пользователя, значение задаёт разработчик.

Период через СтандартныйПериод

Классический приём для отчёта за период. В тексте запроса используют &НачалоПериода и &КонецПериода. На вкладке Параметры добавляют ещё один параметр Период с типом СтандартныйПериод.

Дальше у служебных параметров заполняют поле «Выражение»:

  • у НачалоПериода — &Период.ДатаНачала;
  • у КонецПериода — &Период.ДатаОкончания.

Им же ставят флажок ограничения доступности. Пользователь видит одно привычное поле выбора периода с вариантами «Этот месяц», «Прошлый квартал» и так далее. ДатаОкончания у стандартного периода уже указывает на конец дня, так что проблема потерянного последнего дня здесь не возникает.

Как вывести параметр в шапку отчёта

Чтобы параметр отображался над таблицей, а не прятался в настройках, откройте в редакторе схемы вкладку Настройки. В нижней части выберите закладку Параметры, отметьте нужный параметр флажком и откройте его свойства элемента пользовательских настроек. Там укажите режим отображения «Быстрый доступ».

Установка параметра СКД из кода

Если отчёт формируется программно или значение нужно подставить при открытии формы, обращаются к настройкам компоновщика:

Настройки = КомпоновщикНастроек.Настройки;
Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("Организация", Организация);

Когда параметр включён в пользовательские настройки, значение надо менять ещё и в КомпоновщикНастроек.ПользовательскиеНастройки. Иначе при формировании пользовательская настройка перекроет то, что вы установили в основных.

Параметры динамического списка на форме

Динамический список с произвольным запросом тоже принимает параметры. Включите у реквизита формы флажок «Произвольный запрос», напишите в тексте &Владелец и установите значение в модуле формы:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	Список.Параметры.УстановитьЗначениеПараметра("Владелец", Параметры.Владелец);
КонецПроцедуры

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

Параметр, которому не задали значение, — частая причина пустого списка при открытии формы. Устанавливайте все параметры уже в ПриСозданииНаСервере, хотя бы пустыми ссылками нужного типа.

Параметры и скорость запроса

Сам факт использования параметра на скорость не влияет. Влияет то, где стоит условие.

Отбор переносите в параметры виртуальной таблицы. Сравните два варианта:

// Медленно: сначала считаются остатки по всем складам, потом отсекаются лишние
ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки(&Период) КАК Остатки
ГДЕ Остатки.Склад = &Склад

// Быстро: отбор применяется ещё при расчёте остатков
ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Склад = &Склад) КАК Остатки

На небольшой базе разница незаметна. На регистре с миллионами записей — это секунды против минут.

Ещё несколько правил:

  • 🚀 Длинный список в условии В (сотни и тысячи значений) лучше передать таблицей значений, поместить во временную таблицу и соединиться с ней. Индексируйте её: ИНДЕКСИРОВАТЬ ПО Номенклатура.
  • 🚀 Не вызывайте запрос в цикле с новым значением параметра на каждой итерации. Соберите все значения в массив и выполните один запрос с В (&Список).
  • 🚀 Не оборачивайте поле функцией ради сравнения с параметром. НАЧАЛОПЕРИОДА(Документ.Дата, ДЕНЬ) = &Дата не даёт использовать индекс по дате. Условие Документ.Дата МЕЖДУ &Начало И &Конец даёт.
  • 🚀 Пакетный запрос с временными таблицами использует одни и те же параметры во всех запросах пакета. Устанавливать их повторно не нужно.

Ошибки при установке параметров и как их найти

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

Диагностика: выберите симптом

Регистр букв и составные типы

Регистр в имени параметра не важен: &ОРГАНИЗАЦИЯ и УстановитьПараметр("Организация", ...) найдут друг друга. А вот тип важен всегда.

Если поле составного типа (например, регистратор), а вы сравниваете его с параметром-ссылкой, платформа сравнит корректно. Но если передать в такое условие Неопределено, получите только записи с пустым значением, а не «любые». Для отключения отбора нужен отдельный вариант текста запроса.

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

Можно ли установить параметр после выполнения запроса и выполнить его снова?
Да. Объект Запрос сохраняет текст и параметры. Установите новое значение и снова вызовите Выполнить() — запрос отработает с новым значением, текст заново задавать не нужно.
Как передать в параметр значение «любой» и отключить отбор?
Отдельным параметром-флагом: ГДЕ (&БезОтбора ИЛИ Документ.Организация = &Организация). Передайте Истина в БезОтбора, и условие по организации перестанет работать. На больших таблицах надёжнее собрать два варианта текста.
Сколько значений можно передать в условие В?
Жёсткого лимита в платформе нет, но очень длинный список раздувает текст запроса к СУБД. При сотнях значений и больше передавайте таблицу значений и соединяйтесь с временной таблицей.
Можно ли использовать параметр в запросе с ВЫБОР КОГДА?
Да. Параметр допустим в любом выражении, в том числе в ВЫБОР КОГДА &Режим = 1 ТОГДА … КОНЕЦ и в вычисляемых полях выборки.
Где посмотреть, какие параметры ожидает готовый запрос?
Вызовите Запрос.НайтиПараметры() — вернётся коллекция с именами. В консоли запросов параметры подтягиваются в таблицу автоматически после разбора текста.