Параметры в запросах 1С 8.3: передача значений, списков и таблиц из кода

· 9 мин

Содержание

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

Типичная ситуация: отчёт по остаткам работал, пока его не попросили фильтровать по складу. Вы дописали условие в текст, а значение склада в запрос не передали, и пользователь видит ошибку.

Как объект Запрос получает параметры

У объекта Запрос три свойства, с которыми работают постоянно:

  • 📝 Текст — строка на языке запросов, где параметры отмечены амперсандом;
  • 📦 Параметры — коллекция значений, имеет тип Структура: ключ — имя параметра, значение — то, что подставится в запрос;
  • 🗂 МенеджерВременныхТаблиц — нужен, если запрос создаёт временные таблицы или читает их из другого запроса.

Минимальный рабочий пример выглядит так:

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

Запрос.УстановитьПараметр("ИНН", "7707083893");

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
	Сообщить(Выборка.Контрагент);
КонецЦикла;

Объект Запрос доступен на сервере, в толстом клиенте и во внешнем соединении. В управляемой форме код с запросом выносят в процедуру с директивой &НаСервере или в общий серверный модуль. На тонком клиенте конструктор Новый Запрос недоступен.

Зачем вообще параметры, если можно склеить строку? Склейка ломается на ссылках, датах и строках с кавычками, а значение из поля ввода превращается в кусок текста запроса. Параметр передаётся как значение нужного типа, без разбора текста.

Синтаксис УстановитьПараметр и коллекции Параметры

Сигнатура метода простая:

Запрос.УстановитьПараметр(<Имя>, <Значение>);
  • <Имя> — строка, совпадающая с именем в тексте без &. Должна быть корректным идентификатором: буквы, цифры, подчёркивание, первой не цифра.
  • <Значение> — значение любого типа, который понимает язык запросов: ссылка, число, строка, дата, булево, Неопределено, Тип, Граница, МоментВремени, а также коллекции (о них в следующем разделе).

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

Поскольку Запрос.Параметры — это структура, к ней применимы обычные методы структуры:

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

// проверить, передали ли значение
Если Не Запрос.Параметры.Свойство("Склад") Тогда
	ВызватьИсключение "Не передан склад";
КонецЕсли;

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

Даты и периоды

Дата в 1С всегда содержит время. Условие Документ.Дата <= &КонецПериода с датой 31.03.2026 00:00:00 отрежет все документы, проведённые 31 марта днём. Поэтому конец периода передают так:

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

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

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

Если нужны остатки строго на момент конкретного документа, передают Документ.МоментВремени() или Новый Граница(Документ.МоментВремени(), ВидГраницы.Исключая) — без движений самого документа.

Строки и ПОДОБНО

Для поиска по части наименования шаблон собирают в коде, а в тексте оставляют только параметр:

// в тексте: ГДЕ Номенклатура.Наименование ПОДОБНО &Шаблон
Запрос.УстановитьПараметр("Шаблон", "%" + СтрокаПоиска + "%");

Если пользователь может ввести символы %, _ или [, их нужно экранировать и указать в тексте ПОДОБНО &Шаблон СПЕЦСИМВОЛ "~", иначе они сработают как подстановочные.

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

Одним параметром можно передать сразу набор значений. Сравнение тогда пишут через В:

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

Что подходит для условия В (&Параметр):

Тип значенияКогда удобенНа что смотреть
Массивзначения набраны в кодесамый лёгкий вариант
ФиксированныйМассивзначения пришли из реквизита формы или кэшаработает так же, как массив
СписокЗначенийзначения выбраны пользователем в формеберутся значения, представления игнорируются
ТаблицаЗначенийнужен отбор по колонке готовой таблицыпередавайте таблицу из одной колонки или выгрузку колонки в массив

Частый приём — выгрузить колонку и передать массив: ТЗ.ВыгрузитьКолонку("Номенклатура"). Пустой массив допустим: условие В просто не найдёт ни одной строки.

Таблица значений как источник данных

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

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

Колонки такой таблицы должны иметь заданный тип значения. Если создать колонку через ТЗ.Колонки.Добавить("Количество") без описания типов, запрос не сможет определить тип поля и выдаст ошибку. Правильно так:

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

Таблица, полученная из табличной части через Выгрузить(), типы уже содержит, ничего дописывать не нужно.

Параметры в конструкторе запроса

Конструктор запроса открывают в Конфигураторе или в редакторе модуля: поставьте курсор внутрь текста запроса или на пустую строку, вызовите контекстное меню и выберите «Конструктор запроса». Есть и вариант «Конструктор запроса с обработкой результата» — он сразу сгенерирует код с объектом Запрос, циклом по выборке и строками УстановитьПараметр.

Где параметры появляются в конструкторе

  1. Вкладка «Условия». Перетащите поле в список условий. Конструктор сам подставит параметр с именем поля, например Склад = &Склад. Имя можно исправить прямо в строке условия.
  2. Произвольное условие. Включите флажок «Произвольное» и напишите выражение вручную, например Остатки.КоличествоОстаток > &МинимальныйОстаток.
  3. Параметры виртуальной таблицы. Выделите таблицу Остатки или ОстаткиИОбороты в списке выбранных таблиц и нажмите кнопку «Параметры виртуальной таблицы». В поле периода впишите &Период, в условие — Склад = &Склад.
  4. Вычисляемые поля. Параметр можно использовать и в выражении поля, например &ДатаОтчета КАК ДатаОтчета.

Отбор по складу лучше ставить в параметры виртуальной таблицы Остатки, а не в ГДЕ. Тогда платформа отфильтрует данные при расчёте остатков, а не после него, и запрос будет работать заметно быстрее на больших регистрах.

После нажатия «ОК» конструктор вернёт только текст. Строки УстановитьПараметр за вас допишет лишь вариант «с обработкой результата». В обычном режиме перечислите параметры сами: самый надёжный способ — пройтись поиском по тексту на символ &.

Необязательный отбор: параметр, который могут не заполнить

В отчётах и обработках пользователь часто оставляет поле отбора пустым и ждёт, что увидит «всё». Есть два рабочих подхода.

Условие в самом тексте. Передаёте параметр всегда, а в тексте учитываете пустое значение:

// в тексте:
// ГДЕ (&Контрагент = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)
//      ИЛИ Документ.Контрагент = &Контрагент)
Запрос.УстановитьПараметр("Контрагент", Контрагент);

Текст один, но такое условие хуже использует индексы на больших таблицах.

Сборка текста в коде. Условие добавляют, только если отбор задан:

ТекстУсловия = "";
Если ЗначениеЗаполнено(Контрагент) Тогда
	ТекстУсловия = " И Документ.Контрагент = &Контрагент";
	Запрос.УстановитьПараметр("Контрагент", Контрагент);
КонецЕсли;
Запрос.Текст = СтрЗаменить(Запрос.Текст, "//УсловиеКонтрагент", ТекстУсловия);

Здесь в тексте заранее ставят маркер-комментарий //УсловиеКонтрагент после основного условия ГДЕ. Значение по-прежнему идёт через параметр, склеивается только служебная часть текста.

ПодходПлюсыМинусы
Условие с ИЛИ в текстеодин текст, легко читать и отлаживатьна больших объёмах медленнее
Сборка текста в кодеоптимальный план запросатекст сложнее проверить в конструкторе

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

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

Отчёт на СКД. Когда вы пишете &Период в тексте набора данных, параметр автоматически появляется на вкладке «Параметры» схемы. Там задают его заголовок, тип, значение по умолчанию и флажок ограничения доступности. Из кода значение передают через настройки:

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

Динамический список в форме. Если у реквизита формы типа ДинамическийСписок включён произвольный запрос с параметром, значение передают в обработчике формы, обычно ПриСозданииНаСервере:

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

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

Отладка: проверяем, что попало в параметры

Когда запрос возвращает не то, первое подозрение — значения параметров. Проверяют так:

  1. Поставьте точку останова на строке Запрос.Выполнить() (клавиша F9 в Конфигураторе) и запустите отладку.
  2. Выделите Запрос.Параметры и откройте окно вычисления выражения (Shift+F9). Раскройте структуру: видно каждое имя, значение и его тип.
  3. Проверьте типы. Если вместо ссылки на склад лежит строка с наименованием или число, условие не сработает, хотя ошибки не будет.
  4. Для сверки списка имён вычислите Запрос.НайтиПараметры(). Метод возвращает описание всех параметров, найденных в тексте, — его удобно сравнить с тем, что лежит в Запрос.Параметры.

Чтобы прогнать запрос отдельно от кода, скопируйте Запрос.Текст из окна вычисления в консоль запросов (внешняя обработка для разработчиков), задайте там параметры вручную и посмотрите результат. Так быстро становится понятно, где проблема: в тексте или в значениях, которые передаёт код.

Проверка параметров перед выполнением запроса
Выполнено: 0 / 6

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

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

Ещё две ловушки, которые встречаются при доработке чужого кода:

  • 🔁 Пакетный запрос. Параметры общие для всех запросов пакета. Один и тот же &Период в первом и третьем запросе получит одно значение — передать разные под одним именем нельзя, дайте им разные имена.
  • 🧩 Один объект Запрос в цикле. Значения с прошлой итерации остаются в коллекции. Если на очередном шаге отбор не нужен, а условие в тексте осталось, сработает старое значение. Перед каждой итерацией либо переустанавливайте все параметры, либо очищайте коллекцию: Запрос.Параметры.Очистить().
Можно ли использовать один параметр в тексте несколько раз?
Да. &Организация может стоять и в условии виртуальной таблицы, и в ГДЕ, и в поле выборки. Значение передают один раз.
Можно ли передать в параметр тип, а не значение?
Да, передайте значение типа Тип, например Тип("ДокументСсылка.РеализацияТоваровУслуг"), и сравнивайте в тексте через ТИПЗНАЧЕНИЯ(Поле) = &ТипДокумента.
Как передать пустую ссылку?
В коде — через менеджер: Справочники.Склады.ПустаяСсылка(). В тексте запроса параметр не нужен, можно написать ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка).
Сколько значений можно передать в условие В?
Жёсткий предел зависит от СУБД, но уже на нескольких тысячах значений запрос замедляется. Большой список надёжнее передать таблицей значений во временную таблицу и соединить с ней.
Почему параметр не подставляется в текст при просмотре Запрос.Текст?
Так и должно быть: подстановки в строку нет. Значения хранятся отдельно в Запрос.Параметры и передаются платформе при выполнении.