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

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

Запрос УстановитьПараметр в 1С 8.3: как работает метод и как его правильно использовать

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

Метод УстановитьПараметр объекта «Запрос» в 1С 8.3 подставляет конкретное значение вместо именованного параметра, указанного в тексте запроса через амперсанд (&ИмяПараметра). Без вызова этого метода платформа не знает, чем заменить параметр, и при выполнении запроса возникнет ошибка либо результат будет пустым. Понимание того, как работает передача параметров, — базовый навык для любого разработчика, который пишет выборки из базы данных.

Механизм параметров решает сразу несколько задач. Во-первых, он отделяет текст запроса от данных, что делает код чище и безопаснее: значения не подставляются конкатенацией строк. Во-вторых, один и тот же текст запроса можно выполнять многократно с разными значениями, просто меняя параметры. В-третьих, платформа корректно обрабатывает типы данных — даты, ссылки, списки и таблицы значений передаются без ручного преобразования в строку.

В этой статье разобраны синтаксис метода, порядок установки параметров, особенности передачи списков и таблиц значений, типичные ошибки и способы проверить, что параметр действительно применился.

Как устроен механизм параметров запроса

Параметр в тексте запроса обозначается символом амперсанда перед именем: &Период, &Номенклатура, &СписокСкладов. Когда запрос выполняется, платформа ищет в коллекции параметров значение с соответствующим именем и подставляет его в SQL-запрос, который уходит на сервер базы данных. Имя параметра нечувствительно к регистру, но должно совпадать по написанию.

Объект «Запрос» создаётся конструктором Новый Запрос(ТекстЗапроса) или с последующим присвоением свойства Текст. После этого для каждого параметра вызывается Запрос.УстановитьПараметр("Имя", Значение), и только затем запрос выполняется. Если параметр объявлен в тексте, но не установлен, платформа выдаст ошибку вида «Параметр ""Имя"" не установлен».

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

Синтаксис и базовый пример

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

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

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

"ВЫБРАТЬ

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

| Товары.Наименование

|ИЗ

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

|ГДЕ

| Товары.Родитель = &Группа

| И НЕ Товары.ПометкаУдаления";

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

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

Выборка = Результат.Выбрать();

Здесь параметр Группа получает ссылку на элемент справочника. Платформа сама преобразует ссылку в формат, понятный СУБД. Обратите внимание: в метод передаётся строка "Группа" без символа & — это частая ошибка новичков.

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

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

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

Тип значенияКак использовать в запросеОграничение
Число, строка, дата, булевоПрямое сравнение: = &ЗначениеДата передаётся без времени только если так задумано — время по умолчанию 00:00:00
Ссылка на объектСравнение, обращение к полям через точкуТип ссылки должен совпадать с типом поля
Массив, список значенийОператор В (&Список)Нельзя сравнивать через равенство
Таблица значенийПомещение во временную таблицу: ПОМЕСТИТЬ ВТ ИЗ &ТЗТребует описания колонок в тексте запроса

Отдельного внимания заслуживает передача границ периода. Если нужно выбрать документы за день, помните, что дата в 1С хранится с точностью до секунды. Значение КонецДня(Дата) даст 23:59:59, а передача просто даты без времени отсечёт все документы, созданные после полуночи. Для виртуальных таблиц регистров накопления вместо параметра даты часто используют объект «Граница», чтобы включить или исключить запись на момент времени.

Передача списка значений и оператор В

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

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

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

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

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

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

"ВЫБРАТЬ Остатки.Номенклатура, Остатки.КоличествоОстаток

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

Условие Склад В (&Склады) сработает корректно, только если параметр содержит коллекцию. Если передать одиночную ссылку, запрос выполнится, но логика отбора может оказаться неожиданной. Обратная ситуация — передать массив туда, где в тексте стоит простое равенство = &Склады, — приведёт к ошибке несоответствия типов.

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

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

Таблица значений передаётся в запрос через параметр и помещается во временную таблицу. Это основной способ отфильтровать данные по произвольному набору пар «номенклатура–характеристика» или по результатам предыдущей обработки.

Запрос.УстановитьПараметр("ТаблицаТоваров", ТаблицаЗначений);

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

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

"ВЫБРАТЬ Т.Номенклатура, Т.Количество

|ПОМЕСТИТЬ ВТ_Товары

|ИЗ &ТаблицаТоваров КАК Т

|;

|ВЫБРАТЬ Остатки.Номенклатура, Остатки.КоличествоОстаток

|ИЗ ВТ_Товары КАК Т

|ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки

|ПО Т.Номенклатура = Остатки.Номенклатура";

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

Порядок действий и проверка результата

Порядок действий
  1. 1
    Создайте объект: Запрос = Новый Запрос и задайте свойство Текст с параметрами через &
  2. 2
    Для каждого параметра вызовите Запрос.УстановитьПараметр(Имя, Значение) без амперсанда в имени
  3. 3
    Если используются временные таблицы, назначьте Запрос.МенеджерВременныхТаблиц
  4. 4
    Выполните запрос: Выполнить(), Выбрать() или Выгрузить()
  5. 5
    Проверьте результат: Результат.Пустой() показывает, вернулись ли данные

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

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

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

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

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

Метод вызван для каждого & в тексте, запрос выполняется без ошибок

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

Ошибка «Параметр не установлен» при выполнении

Корректность отбора по дате
Норма

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

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

Документы последнего дня периода отсутствуют — вероятно, дата передана без конца дня

Отбор по списку
Норма

В тексте оператор В (&Список), параметр — массив или список значений

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

Ошибка типов или отбор только по одному значению

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

Типичные ошибки
01
Амперсанд в имени: УстановитьПараметр("&Период", ...) — параметр не будет найден, имя указывается без &
02
Установка параметра после Выполнить() — значение не применится, порядок вызовов нарушен
03
Передача одиночного значения в оператор В — сравнение работает не так, как ожидается, или падает с ошибкой
04
Одинаковые имена параметров с разным смыслом в пакетном запросе — значение перезаписывается, и обе части пакета получают последнее значение
05
Передача Неопределено вместо пустой ссылки — ошибка типизации в условии сравнения

Отдельная группа проблем связана с пакетными запросами. Параметры общие для всего пакета: если в двух запросах пакета используется &Дата, оба получат одно значение. Это удобно, но требует дисциплины в именовании — давайте параметрам говорящие имена, чтобы случайно не переиспользовать имя с другим смыслом.

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

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

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

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

При выполнении запроса платформа выдаст ошибку о том, что параметр не установлен. Запрос не выполнится, поэтому такая ошибка обнаруживается сразу при тестировании, а не приводит к скрытым некорректным данным.

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

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

Как передать в параметр значение NULL?

Передайте значение NULL напрямую нельзя — вместо этого в тексте запроса используют конструкции ЕСТЬ NULL или значение Неопределено, которое платформа при выполнении преобразует в NULL. Для сравнения с NULL в условии применяйте оператор ЕСТЬ NULL, а не равенство.

Работает ли УстановитьПараметр для полей динамического списка?

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

Почему запрос с параметром-таблицей значений выполняется медленно?

Чаще всего причина в избыточном объёме таблицы (лишние строки и колонки) или в отсутствии индекса у временной таблицы. Сократите состав колонок до участвующих в соединении, добавьте в текст запроса секцию ИНДЕКСИРОВАТЬ ПО для полей соединения и уберите дубли строк перед передачей.

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

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

Итог

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

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