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

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

Как передать параметр во вложенный запрос в 1С

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

Передача параметров во вложенный запрос — одна из самых частых задач при работе с языком запросов 1С. Вложенные запросы используются в секциях ВЫБРАТЬ, в соединениях таблиц и в условиях ГДЕ, и во всех этих случаях параметры объявляются одинаково — через амперсанд в тексте запроса и метод УстановитьПараметр у объекта Запрос.

Ключевая особенность, которую нужно понять сразу: у объекта Запрос единая область видимости параметров. Неважно, насколько глубоко вложен подзапрос — в первом уровне, в третьем или в пакетном запросе — параметр объявляется один раз через УстановитьПараметр, и он становится доступен везде, где встречается в тексте. Это одновременно упрощает работу и порождает типичные ошибки, связанные с конфликтом имён.

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

Как работают параметры в запросах 1С

Параметр в тексте запроса обозначается символом амперсанда перед именем: &Период, &Ссылка, &Организация. Когда запрос выполняется, платформа подставляет вместо параметра реальное значение, которое вы задали программно. Если значение не задано, при выполнении возникнет ошибка «Переменная не определена».

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

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

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

"ВЫБРАТЬ

| Продажи.Номенклатура КАК Номенклатура,

| Продажи.Количество КАК Количество

|ИЗ

| РегистрНакопления.Продажи КАК Продажи

|ГДЕ

| Продажи.Период МЕЖДУ &НачалоПериода И &КонецПериода";

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

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

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

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

Передача параметра во вложенный запрос: базовый пример

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

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

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

"ВЫБРАТЬ

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

| Цены.Цена КАК Цена

|ИЗ

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

| ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ

| ЦеныНоменклатуры.Номенклатура КАК Номенклатура,

| ЦеныНоменклатуры.Цена КАК Цена

| ИЗ

| РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры

| ГДЕ

| ЦеныНоменклатуры.ТипЦен = &ТипЦен) КАК Цены

| ПО Номенклатура.Ссылка = Цены.Номенклатура

|ГДЕ

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

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

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

Обратите внимание: параметр &ТипЦен встречается только во вложенном запросе, но никаких дополнительных действий не требуется. Платформа сама находит параметр на любом уровне вложенности и подставляет значение.

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

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

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

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

"ВЫБРАТЬ

| Документы.Ссылка КАК Ссылка

|ПОМЕСТИТЬ ВТ_Документы

|ИЗ

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

|ГДЕ

| Документы.Контрагент = &Контрагент

| И Документы.Проведен

|;

|

|ВЫБРАТЬ

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

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

| Товары.Сумма КАК Сумма

|ИЗ

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

|ГДЕ

| Товары.Ссылка В (ВЫБРАТЬ ВТ_Документы.Ссылка ИЗ ВТ_Документы)";

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

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

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

Типичные ошибки
01
Использовать одно имя параметра для разных смыслов в разных подзапросах — значение подставится везде, и отбор сработает неправильно
02
Забыть вызвать УстановитьПараметр перед Выполнить() — запрос упадёт с ошибкой о неопределённой переменной
03
Устанавливать параметр после выполнения запроса — на уже полученный результат это не повлияет
04
Передавать параметр с несовместимым типом данных, например строку вместо ссылки, — сравнение даст пустой результат без явной ошибки

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

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

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

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

"ВЫБРАТЬ

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

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

|ИЗ

| РегистрНакопления.ТоварыНаСкладах.Остатки(

| ,

| Склад В (&Склады)) КАК Остатки";

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

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

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

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

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

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

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

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

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

"ВЫБРАТЬ

| Срез.Номенклатура КАК Номенклатура,

| Срез.Цена КАК Цена

|ИЗ

| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(

| &Период,

| ТипЦен = &ТипЦен) КАК Срез";

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

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

Если параметр периода не задать (оставить пустым в позиции), срез будет построен на самую позднюю дату в регистре. Для СрезПоследних без периода платформа вернёт актуальные значения, но явное указание периода делает поведение предсказуемым и упрощает отладку.

Как проверить, что параметр передан корректно

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

В коде полезно временно вывести значения параметров перед выполнением через Сообщить() или в журнал регистрации, особенно когда параметр вычисляется программно. Часто оказывается, что вместо ссылки передаётся строковое представление или Неопределено.

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

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

Запрос выполняется без ошибок
Норма

Все параметры объявлены через УстановитьПараметр до Выполнить()

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

Ошибка «Переменная не определена» — параметр не установлен или имя написано с опечаткой

Результат отбора
Норма

Выборка содержит ожидаемые строки по заданному условию

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

Пустой результат при корректном тексте — проверьте тип значения параметра и непустой ли массив

Повторные выполнения
Норма

После смены значения параметра результат меняется

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

Результат не меняется — параметр установлен после Выполнить() или запрос выполнен повторно без новой установки

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

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

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

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

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

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

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

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

Чаще всего массив пуст или содержит значения не того типа (например, строки вместо ссылок). Проверьте содержимое коллекции перед УстановитьПараметр и убедитесь, что типы совпадают с типом сравниваемого поля.

Работают ли параметры в запросах динамических списков и СКД?

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

Итог

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

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