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

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

Что такое параметр в запросе 1С и как с ним работать

Что такое параметр в запросе 1С, как объявить и передать параметр через УстановитьПараметр, типичные ошибки и примеры кода на встроенном языке.

Параметр в запросе 1С — это именованное значение, которое подставляется в текст запроса в момент его выполнения. В тексте запроса параметр записывается с символом амперсанда, например &Контрагент, а фактическое значение передаётся из кода через метод УстановитьПараметр() до вызова Выполнить().

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

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

Как выглядит параметр в тексте запроса

В тексте запроса параметр обозначается символом & перед именем. Имя подчиняется обычным правилам идентификаторов: начинается с буквы, не содержит пробелов и спецсимволов. Один и тот же параметр можно использовать в тексте несколько раз — значение подставится везде.

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

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

"ВЫБРАТЬ

| РеализацияТоваровУслуг.Ссылка,

| РеализацияТоваровУслуг.СуммаДокумента

|ИЗ

| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг

|ГДЕ

| РеализацияТоваровУслуг.Контрагент = &Контрагент

| И РеализацияТоваровУслуг.Дата МЕЖДУ &НачалоПериода И &КонецПериода";

Запрос.УстановитьПараметр("Контрагент", ВыбранныйКонтрагент);

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

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

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

Обратите внимание: в методе УстановитьПараметр() имя указывается без амперсанда и в кавычках — это строка. Порядок вызовов не важен, главное — установить все параметры до выполнения запроса.

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

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

Тип параметра не объявляется заранее: платформа определяет его по переданному значению. Из-за этого возможна ошибка несовместимости типов, если, например, в условии сравнения с датой передать строку. Проверяйте типы значений до установки параметра, особенно когда значение приходит из пользовательского ввода.

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

Параметры в условиях отбора: В, В ИЕРАРХИИ и списки

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

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

"ВЫБРАТЬ

| Товары.Ссылка

|ИЗ

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

|ГДЕ

| Товары.Родитель В ИЕРАРХИИ(&Группы)";

МассивГрупп = Новый Массив;

МассивГрупп.Добавить(ГруппаЭлектроника);

МассивГрупп.Добавить(ГруппаБытоваяТехника);

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

Оператор В ИЕРАРХИИ работает только для полей иерархических справочников и планов видов характеристик. Если справочник неиерархический, используйте обычный В. Учтите, что проверка иерархии выполняется на сервере СУБД и при больших списках групп может замедлять запрос — для тяжёлых отчётов иногда выгоднее вычислить состав групп заранее.

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

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

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

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

"ВЫБРАТЬ

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

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

|ИЗ

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

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

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

Здесь важны два момента. Первый: граница периода для остатков обычно задаётся концом дня или объектом Граница с видом «Включая», иначе движения на граничный момент могут не попасть в результат. Второй: условия внутри параметров виртуальной таблицы выполняются до соединения с другими таблицами, поэтому отбор лучше размещать именно там, а не в секции ГДЕ — это быстрее.

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

Таблицу значений можно передать в запрос как параметр и поместить во временную таблицу с помощью конструкции ПОМЕСТИТЬ. Это основной способ соединить данные, вычисленные в коде, с данными информационной базы.

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

Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;

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

"ВЫБРАТЬ

| ВнешниеДанные.Код,

| ВнешниеДанные.Количество

|ПОМЕСТИТЬ ВТ_Данные

|ИЗ

| &ТаблицаДанных КАК ВнешниеДанные

|;

|ВЫБРАТЬ

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

| ВТ_Данные.Количество

|ИЗ

| ВТ_Данные КАК ВТ_Данные

| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура

| ПО ВТ_Данные.Код = Номенклатура.Код";

Запрос.УстановитьПараметр("ТаблицаДанных", ТаблицаИзФайла);

Чтобы временная таблица была доступна между несколькими запросами или пакетами, объекту запроса нужно назначить менеджер временных таблиц. Без него временные таблицы живут только в пределах одного выполнения пакета. Также помните: таблица значений, переданная параметром, целиком материализуется на сервере СУБД, поэтому передача очень больших таблиц (сотни тысяч строк) может ощутимо нагрузить систему.

Порядок работы с параметром
  1. 1
    Напишите текст запроса, обозначив параметры через &Имя
  2. 2
    Проверьте и приведите типы значений в коде (даты, ссылки, массивы)
  3. 3
    Вызовите УстановитьПараметр() для каждого параметра
  4. 4
    Выполните запрос и проверьте результат на тестовых данных
  5. 5
    Убедитесь, что не забытые параметры не вызывают ошибку выполнения

Типичные ошибки при работе с параметрами

Самая частая ошибка — «Ошибка при выполнении запроса: параметр не задан». Она возникает, когда параметр есть в тексте, но УстановитьПараметр() для него не вызван, либо имя в вызове отличается от имени в тексте (опечатка, лишний пробел). Имена параметров чувствительны к точному написанию, хотя и не к регистру.

Вторая группа ошибок связана с типами: строка вместо даты, код вместо ссылки, Неопределено вместо пустой ссылки. Запрос при этом либо падает с ошибкой несоответствия типов, либо молча возвращает пустой результат — второй вариант опаснее, потому что его трудно заметить.

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

Типичные ошибки
01
Параметр указан в тексте, но УстановитьПараметр не вызван — запрос падает с ошибкой
02
В параметр передано Неопределено вместо пустой ссылки — условие не срабатывает
03
Пустой массив в операторе В — запрос возвращает ноль строк без предупреждения
04
Попытка передать имя таблицы или поля параметром — параметры подставляют только значения
05
Отбор по виртуальной таблице в секции ГДЕ вместо параметров таблицы — лишняя нагрузка на СУБД

Как проверить, что параметры работают правильно

Базовая проверка — выполнить запрос в консоли запросов (типовой инструмент в режиме предприятия или внешняя обработка) с теми же значениями параметров и сравнить результат с выборкой из кода. Консоль показывает список всех параметров, найденных в тексте, что сразу выявляет опечатки в именах.

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

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

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

Все ли параметры установлены
Норма

Для каждого &Имя в тексте есть вызов УстановитьПараметр

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

Запрос падает с ошибкой «параметр не задан»

Типы значений
Норма

Даты — тип Дата, ссылки — ссылки нужного вида, списки — массив или список значений

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

Ошибка несоответствия типов или пустой результат

Границы периода
Норма

Остатки на конец дня или Граница с видом Включая

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

Документы граничного момента не попадают в результат

Заполненность списков
Норма

Массив содержит хотя бы один элемент или условие не добавляется

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

Пустой массив обнуляет выборку

Итог

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

Параметр — это &Имя в тексте запроса и значение через УстановитьПараметр() до выполнения. Параметры подставляют только значения, а не имена таблиц и полей. Для списков используйте В с массивом, для виртуальных таблиц — параметры в скобках, для внешних данных — таблицу значений с ПОМЕСТИТЬ. Проверяйте типы и заполненность значений до выполнения запроса.

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

Чем параметр отличается от переменной встроенного языка в запросе?

Переменная встроенного языка существует только в коде, запрос её «не видит». Чтобы значение переменной попало в запрос, его нужно передать через УстановитьПараметр. Параметр — это точка подстановки внутри текста запроса, которую платформа заполняет в момент выполнения.

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

Да. Если параметр &Период встречается в тексте пять раз, достаточно одного вызова УстановитьПараметр("Период", Значение) — значение подставится во все места. Это удобно для повторяющихся отборов и снижает риск рассинхронизации значений.

Как передать в запрос список документов или контрагентов?

Сформируйте массив или список значений со ссылками, передайте его параметром и используйте оператор В: ГДЕ Документ.Контрагент В (&Контрагенты). Для иерархических справочников применяйте В ИЕРАРХИИ. Перед выполнением проверьте, что коллекция не пуста.

Почему запрос с параметром-датой не находит документы за последний день периода?

Чаще всего дата передана как начало дня (время 00:00:00), а документы проведены в течение дня. Передавайте КонецДня(Дата) или объект Граница с видом «Включая», чтобы весь последний день попал в выборку.

Можно ли через параметр задать имя таблицы или поля?

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

Что делать, если параметр может быть не заполнен пользователем?

Обработайте этот случай в коде: либо не добавляйте соответствующее условие в текст запроса (формируйте текст динамически), либо добавьте в условие проверку вида (&Отбор = НЕОПРЕДЕЛЕНО ИЛИ Поле = &Отбор). Первый вариант предпочтительнее, так как не замедляет запрос лишними проверками.