К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как задать значение параметра в запросе 1С

Как задать значение параметра в запросе 1С: метод УстановитьПараметр, передача массивов, дат и ссылок, типичные ошибки и способы проверки результата.

Параметры запроса в 1С — основной способ передать в текст запроса значения из кода: ссылки на документы и справочники, даты, списки значений, строки и числа. Правильно заданный параметр делает запрос безопасным, читаемым и быстрым: платформа не собирает текст запроса конкатенацией строк, а передаёт значения напрямую в механизм СУБД.

За передачу значений отвечает метод УстановитьПараметр() объекта «Запрос». Он вызывается после заполнения свойства Текст и до вызова Выполнить(). Имя параметра в тексте запроса начинается с символа &, а в методе устанавливается без него.

Ошибки при работе с параметрами — одна из самых частых причин пустых выборок, исключений «Параметр не найден» и неожиданно медленных запросов. Ниже разобраны синтаксис, передача значений разных типов, работа со списками, проверка результата и типичные ошибки.

Базовый синтаксис: как объявить и установить параметр

Минимальный рабочий пример выглядит так: создаётся объект запроса, задаётся текст с параметром, затем параметру присваивается значение.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Номенклатура.Ссылка КАК Товар,

| Номенклатура.Наименование КАК Наименование

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

| Номенклатура.Родитель = &Группа";

Запрос.УстановитьПараметр("Группа", ГруппаТоваров);

Результат = Запрос.Выполнить();

Обратите внимание на три правила. Во-первых, в тексте запроса параметр пишется с амперсандом — &Группа, а в методе УстановитьПараметр имя указывается строкой без амперсанда. Во-вторых, имена параметров нечувствительны к регистру, но лучше выдерживать единый стиль. В-третьих, один и тот же параметр можно использовать в тексте несколько раз — значение задаётся один раз.

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

Какие типы значений можно передавать в параметр

Параметром может быть практически любой тип, который платформа умеет сопоставить с типами полей базы данных: строки, числа, булево, даты, ссылки на объекты, перечисления, а также массивы, списки значений и таблицы значений. Главное условие — тип значения должен быть сравним с типом поля, с которым параметр сравнивается в условии.

Для дат есть важная деталь: значение типа «Дата» содержит и время. Если нужно отобрать документы за день, сравнение Дата = &Дата с датой без времени вернёт только документы, проведённые ровно в полночь. Правильнее передавать границы периода: начало дня и конец дня, полученные функциями НачалоДня() и КонецДня().

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

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

// В тексте: ГДЕ Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода

Для ссылок передавайте именно ссылку, а не представление или код. Частая ошибка новичков — передать строку с наименованием контрагента и сравнивать её с полем типа «СправочникСсылка». Такое условие либо не сработает, либо вызовет ошибку несоответствия типов. Если у вас есть только код или наименование, сначала найдите ссылку через НайтиПоКоду() или НайтиПоНаименованию().

Передача списков: массивы и списки значений

Когда нужно отобрать данные по нескольким значениям — например, по списку контрагентов или видов документов, — параметру передаётся массив или список значений, а в тексте используется оператор В.

МассивСкладов = Новый Массив;

МассивСкладов.Добавить(СкладОсновной);

МассивСкладов.Добавить(СкладРозничный);

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

// В тексте: ГДЕ Остатки.Склад В (&Склады)

Для иерархических справочников полезен оператор В ИЕРАРХИИ: если передать группу справочника, отбор пройдёт по всем вложенным элементам. Это избавляет от необходимости вручную собирать массив всех подчинённых элементов.

Учтите ограничение: пустой массив в условии В (&Список) приведёт к тому, что запрос не вернёт ни одной строки. Если пустой список означает «без отбора», условие нужно формировать динамически или добавлять проверку в коде.

Параметры в виртуальных таблицах регистров

Виртуальные таблицы регистров накопления и сведений — Остатки, Обороты, СрезПоследних, СрезПервых — принимают параметры в круглых скобках после имени таблицы. Эти параметры устанавливаются тем же методом УстановитьПараметр.

Запрос.Текст =

"ВЫБРАТЬ

| Остатки.Номенклатура КАК Товар,

| Остатки.КоличествоОстаток КАК Остаток

|ИЗ

| РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Склад = &Склад) КАК Остатки";

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

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

Критически важно накладывать отбор именно в параметрах виртуальной таблицы, а не в секции ГДЕ основного запроса. Отбор в параметрах выполняется на уровне итогов и работает на порядки быстрее, особенно на больших регистрах. Условие ГДЕ Остатки.Склад = &Склад вынудит платформу сначала выбрать остатки по всем складам, а потом отфильтровать результат.

Для СрезПоследних первым параметром идёт период, на который берётся срез. Если период не указан, срез строится на самую позднюю дату в регистре — это медленно и часто не то, что требуется по смыслу задачи.

Сравнение вариантов

Отбор в параметрах виртуальной таблицы

Быстро: отбор на уровне итогов СУБД. Подходит для периода и измерений регистра. Ограничение — только равенство и списки.

Отбор в секции ГДЕ

Гибче: любые условия и вычисления. Но на виртуальных таблицах приводит к полному вычислению таблицы до фильтрации — медленно на больших данных.

Временные таблицы с индексацией

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

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

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

В динамических списках форм параметры устанавливаются через коллекцию Параметры компоновки данных:

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

Если ПараметрСписок <> Неопределено Тогда

ПараметрСписок.Значение = ТекущаяОрганизация;

ПараметрСписок.Использование = Истина;

КонецЕсли;

Здесь важно не забыть установить флаг Использование — без него параметр существует, но в запрос не передаётся, и отбор молча не сработает. Это одна из самых коварных причин «нефильтрующегося» динамического списка.

Порядок действий
  1. 1
    Сформулируйте текст запроса и отметьте все параметры с амперсандом
  2. 2
    Проверьте текст в консоли запросов с тестовыми значениями параметров
  3. 3
    Перенесите текст в код и задайте каждый параметр через УстановитьПараметр
  4. 4
    Убедитесь, что типы значений совпадают с типами полей в условиях
  5. 5
    Выполните запрос и проверьте выборку на контрольных данных

Проверка результата и типичные ошибки

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

Контрольные точки

Как проверить результат

Количество строк в выборке
Норма

Совпадает с ожидаемым по контрольным данным

Тревожный признак

Ноль строк или явно больше ожидаемого — проверяйте параметры

Тип значения параметра
Норма

Совпадает с типом поля в условии (ссылка со ссылкой, дата с датой)

Тревожный признак

Строка вместо ссылки, дата без времени вместо границы периода

Отбор виртуальной таблицы
Норма

Условие задано в скобках параметров таблицы

Тревожный признак

Условие вынесено в ГДЕ — запрос тормозит на больших данных

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

Использование = Истина, значение заполнено

Тревожный признак

Параметр задан, но Использование не включено — отбор не работает

Типичные ошибки
01
Амперсанд в имени параметра метода: УстановитьПараметр("&Группа", ...) — параметр не будет найден, имя пишется без &
02
Сравнение даты документа с датой без времени через равенство — выборка пустая, используйте МЕЖДУ с НачалоДня и КонецДня
03
Передача пустого массива в условие В (&Список) — запрос возвращает ноль строк, хотя ожидался отбор без ограничений
04
Установка параметра после вызова Выполнить() — значение не попадает в запрос
05
Отбор по складу или организации в секции ГДЕ вместо параметров виртуальной таблицы — резкое падение производительности
06
В динамическом списке забыто свойство Использование — параметр заполнен, но отбор не применяется

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

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

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

Можно ли задать значение параметра прямо в тексте запроса?

Да, для постоянных значений можно использовать литералы: строки в кавычках, числа, ЗНАЧЕНИЕ(...) для перечислений и предопределённых элементов, ДАТАВРЕМЯ(...) для дат. Но значения, которые приходят из переменных или от пользователя, всегда передавайте через УстановитьПараметр — так код безопаснее и проще в сопровождении.

Что будет, если параметр указан в тексте, но не установлен?

При выполнении запроса платформа выдаст ошибку вида «Не задано значение параметра». Запрос не выполнится, поэтому перед Выполнить() полезно сверить список параметров в тексте со списком вызовов УстановитьПараметр.

Как передать в параметр таблицу значений?

Таблицу значений передают как параметр и в тексте запроса выбирают из неё через конструкцию ПОМЕСТИТЬ с указанием полей: ВЫБРАТЬ Т.Поле ПОМЕСТИТЬ ВТ ИЗ &Таблица КАК Т. Далее временная таблица используется в соединениях. Это стандартный способ передать в запрос произвольный набор данных, например табличную часть документа.

Почему запрос с параметром-датой возвращает пустой результат?

Чаще всего причина во времени: тип «Дата» включает время, и равенство срабатывает только при точном совпадении до секунды. Используйте диапазон: МЕЖДУ НачалоДня(&Дата) И КонецДня(&Дата) или сравнение с границами периода.

Можно ли использовать один параметр несколько раз в запросе?

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

Как задать параметр в запросе динамического списка формы?

Через коллекцию Список.Параметры: найдите параметр методом НайтиЗначениеПараметра с объектом ПараметрКомпоновкиДанных, присвойте Значение и обязательно установите Использование = Истина. Без флага использования отбор не применится.

Итог

Что важно запомнить

Параметры задаются методом УстановитьПараметр после текста запроса и до Выполнить(); в тексте имя пишется с &, в методе — без. Тип значения должен совпадать с типом поля, даты передавайте границами периода, списки — массивами с оператором В. Отборы по измерениям регистров задавайте в параметрах виртуальных таблиц, а в динамических списках не забывайте флаг Использование.