Как правильно обратиться к полю объекта через параметр в запросе 1С?

Программист 1С v8.3 (Управляемые формы) Управленческий учет IT и автоматизация бизнеса
← На главную

При написании запросов в системе 1С:Предприятие начинающие разработчики часто сталкиваются с ошибкой при попытке получить значение реквизита через параметр. Типичная ситуация: в запрос передается ссылка на документ (например, ЗаказПоставщику), и программист пытается ограничить выборку данных, обращаясь к складу этого документа прямо в теле запроса через конструкцию &Ссылка.Склад. Однако платформа выдает ошибку синтаксиса.

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

Причина возникновения проблемы: ограничения парсера запросов

Давайте проанализируем ситуацию. Язык запросов 1С спроектирован таким образом, что параметр (конструкция, начинающаяся с символа &) воспринимается системой как конечное значение определенного типа (ссылка, число, строка или дата). В отличие от встроенного языка 1С, где мы можем написать СсылкаНаДокумент.Склад, в языке запросов нельзя использовать «dot-walking» (обращение через точку) по отношению к параметру.

Рассмотрим ошибочный пример из практики:


ВЫБРАТЬ
    ТоварыНаСкладахОбороты.Номенклатура,
    ТоварыНаСкладахОбороты.ВНаличииРасход КАК Товарооборот
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Обороты(&ДатаНачала, &ДатаОкончания, , Склад = &Ссылка.Склад) КАК ТоварыНаСкладахОбороты

В данном случае система ожидает, что после точки за параметром &Ссылка следует имя поля таблицы, но параметр сам по себе не является таблицей. Это приводит к ошибке "Неверные параметры". Разберем способы обхода этого ограничения.

Решение 1: Передача готового значения в отдельный параметр

Проанализируем самый простой и производительный способ. Вместо того чтобы заставлять запрос «добывать» склад из ссылки, мы можем подготовить это значение заранее в коде на встроенном языке и передать его как самостоятельный параметр.

Выполним следующие шаги в коде 1С:

  1. Получим значение склада из имеющейся ссылки (если объект уже в памяти) или прочитаем его.
  2. Установим новый параметр в объекте Запрос.

Посмотрим на пример реализации:


// Предположим, переменная СсылкаЗаказа содержит ссылку на документ ЗаказПоставщику
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   ТоварыНаСкладахОбороты.Номенклатура КАК Номенклатура,
    |   ТоварыНаСкладахОбороты.ВНаличииРасход КАК Товарооборот
    |ИЗ
    |   РегистрНакопления.ТоварыНаСкладах.Обороты(&ДатаНачала, &ДатаОкончания, , Склад = &ПараметрСклад) КАК ТоварыНаСкладахОбороты";

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

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

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

Преимущество этого метода: Максимальная производительность. СУБД получает в качестве фильтра конкретный уникальный идентификатор (GUID) склада, что позволяет эффективно использовать индексы таблиц.

Решение 2: Использование подзапроса внутри основного запроса

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

Разберем, как это выглядит в тексте запроса:


ВЫБРАТЬ
    ТоварыНаСкладахОбороты.Номенклатура,
    СУММА(ТоварыНаСкладахОбороты.ВНаличииРасход) КАК Товарооборот
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Обороты(
        &ДатаНачала, 
        &ДатаОкончания, , 
        Склад В (ВЫБРАТЬ Т.Склад ИЗ Документ.ЗаказПоставщику КАК Т ГДЕ Т.Ссылка = &Ссылка)
    ) КАК ТоварыНаСкладахОбороты
СГРУППИРОВАТЬ ПО
    ТоварыНаСкладахОбороты.Номенклатура

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

Важное замечание: Будьте осторожны с использованием подзапросов в параметрах виртуальных таблиц. В некоторых случаях это может привести к неоптимальному плану выполнения запроса на стороне SQL-сервера.

Решение 3: Особенности работы в Системе компоновки данных (СКД)

Если вы разрабатываете отчет на базе СКД, ситуация упрощается. Система компоновки данных обладает более продвинутым механизмом обработки параметров. Рассмотрим алгоритм настройки:

  1. Перейдем на закладку "Параметры" в схеме компоновки.
  2. Найдем параметр &Склад.
  3. В колонке "Выражение" напишем: &Ссылка.Склад.

В этом случае при выполнении отчета СКД сама вычислит значение склада от переданной ссылки и подставит его в итоговый SQL-запрос. Это позволяет оставить текст запроса чистым, используя простое условие Склад = &Склад.

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

Проанализируем еще одну ошибку, упомянутую в обсуждении. Попытка использовать параметр прямо в секции ИЗ:


ВЫБРАТЬ
    заказПоставщику.Склад КАК Склад
ПОМЕСТИТЬ складИзЗаказа
ИЗ
    &Ссылка КАК заказПоставщику

Это классическая ошибка понимания структуры запроса. Секция ИЗ в 1С всегда ожидает источник данных — таблицу. Параметр &Ссылка не является таблицей. Если вам нужно получить данные из этого документа во временную таблицу, запрос должен выглядеть так:


ВЫБРАТЬ
    Т.Склад КАК Склад
ПОМЕСТИТЬ складИзЗаказа
ИЗ
    Документ.ЗаказПоставщику КАК Т
ГДЕ
    Т.Ссылка = &Ссылка

Рекомендации и выводы

Подводя итог, проанализируем, какой метод лучше выбрать:

Таким образом, мы выяснили, что прямое обращение &Параметр.Поле запрещено синтаксисом, но платформа предоставляет достаточно инструментов для эффективного обхода этого ограничения.

← На главную