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