При написании запросов в системе 1С:Предприятие начинающие разработчики часто сталкиваются с ошибкой при попытке получить значение реквизита через параметр. Типичная ситуация: в запрос передается ссылка на документ (например, ЗаказПоставщику), и программист пытается ограничить выборку данных, обращаясь к складу этого документа прямо в теле запроса через конструкцию &Ссылка.Склад. Однако платформа выдает ошибку синтаксиса.
В этой статье мы подробно разберем, почему стандартное разыменование полей через точку не работает с параметрами, и рассмотрим несколько эффективных способов решения этой задачи.
Давайте проанализируем ситуацию. Язык запросов 1С спроектирован таким образом, что параметр (конструкция, начинающаяся с символа &) воспринимается системой как конечное значение определенного типа (ссылка, число, строка или дата). В отличие от встроенного языка 1С, где мы можем написать СсылкаНаДокумент.Склад, в языке запросов нельзя использовать «dot-walking» (обращение через точку) по отношению к параметру.
Рассмотрим ошибочный пример из практики:
ВЫБРАТЬ
ТоварыНаСкладахОбороты.Номенклатура,
ТоварыНаСкладахОбороты.ВНаличииРасход КАК Товарооборот
ИЗ
РегистрНакопления.ТоварыНаСкладах.Обороты(&ДатаНачала, &ДатаОкончания, , Склад = &Ссылка.Склад) КАК ТоварыНаСкладахОбороты
В данном случае система ожидает, что после точки за параметром &Ссылка следует имя поля таблицы, но параметр сам по себе не является таблицей. Это приводит к ошибке "Неверные параметры". Разберем способы обхода этого ограничения.
Проанализируем самый простой и производительный способ. Вместо того чтобы заставлять запрос «добывать» склад из ссылки, мы можем подготовить это значение заранее в коде на встроенном языке и передать его как самостоятельный параметр.
Выполним следующие шаги в коде 1С:
Запрос.Посмотрим на пример реализации:
// Предположим, переменная СсылкаЗаказа содержит ссылку на документ ЗаказПоставщику
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ТоварыНаСкладахОбороты.Номенклатура КАК Номенклатура,
| ТоварыНаСкладахОбороты.ВНаличииРасход КАК Товарооборот
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Обороты(&ДатаНачала, &ДатаОкончания, , Склад = &ПараметрСклад) КАК ТоварыНаСкладахОбороты";
// Устанавливаем параметры
Запрос.УстановитьПараметр("ДатаНачала", НачалоДня(ТекущаяДата()));
Запрос.УстановитьПараметр("ДатаОкончания", КонецДня(ТекущаяДата()));
// Именно здесь мы извлекаем склад и передаем его в запрос
Запрос.УстановитьПараметр("ПараметрСклад", СсылкаЗаказа.Склад);
РезультатЗапроса = Запрос.Выполнить();
Преимущество этого метода: Максимальная производительность. СУБД получает в качестве фильтра конкретный уникальный идентификатор (GUID) склада, что позволяет эффективно использовать индексы таблиц.
Иногда возникают ситуации, когда мы не хотим или не можем менять код установки параметров (например, при работе в динамических списках или сложных универсальных отчетах). В этом случае мы можем заставить систему найти склад по ссылке с помощью вложенного запроса к таблице документа.
Разберем, как это выглядит в тексте запроса:
ВЫБРАТЬ
ТоварыНаСкладахОбороты.Номенклатура,
СУММА(ТоварыНаСкладахОбороты.ВНаличииРасход) КАК Товарооборот
ИЗ
РегистрНакопления.ТоварыНаСкладах.Обороты(
&ДатаНачала,
&ДатаОкончания, ,
Склад В (ВЫБРАТЬ Т.Склад ИЗ Документ.ЗаказПоставщику КАК Т ГДЕ Т.Ссылка = &Ссылка)
) КАК ТоварыНаСкладахОбороты
СГРУППИРОВАТЬ ПО
ТоварыНаСкладахОбороты.Номенклатура
Выясним причину, по которой этот метод работает: мы обращаемся к физической таблице метаданных Документ.ЗаказПоставщику, где поле Ссылка используется для фильтрации, а поле Склад выбирается как результат. Этот результат затем подставляется в условие Склад В (...) виртуальной таблицы оборотов.
Важное замечание: Будьте осторожны с использованием подзапросов в параметрах виртуальных таблиц. В некоторых случаях это может привести к неоптимальному плану выполнения запроса на стороне SQL-сервера.
Если вы разрабатываете отчет на базе СКД, ситуация упрощается. Система компоновки данных обладает более продвинутым механизмом обработки параметров. Рассмотрим алгоритм настройки:
&Склад.&Ссылка.Склад.В этом случае при выполнении отчета СКД сама вычислит значение склада от переданной ссылки и подставит его в итоговый SQL-запрос. Это позволяет оставить текст запроса чистым, используя простое условие Склад = &Склад.
Проанализируем еще одну ошибку, упомянутую в обсуждении. Попытка использовать параметр прямо в секции ИЗ:
ВЫБРАТЬ
заказПоставщику.Склад КАК Склад
ПОМЕСТИТЬ складИзЗаказа
ИЗ
&Ссылка КАК заказПоставщику
Это классическая ошибка понимания структуры запроса. Секция ИЗ в 1С всегда ожидает источник данных — таблицу. Параметр &Ссылка не является таблицей. Если вам нужно получить данные из этого документа во временную таблицу, запрос должен выглядеть так:
ВЫБРАТЬ
Т.Склад КАК Склад
ПОМЕСТИТЬ складИзЗаказа
ИЗ
Документ.ЗаказПоставщику КАК Т
ГДЕ
Т.Ссылка = &Ссылка
Подводя итог, проанализируем, какой метод лучше выбрать:
Запрос.УстановитьПараметр("Склад", Ссылка.Склад) является эталонным способом с точки зрения чистоты кода и скорости работы.Таким образом, мы выяснили, что прямое обращение &Параметр.Поле запрещено синтаксисом, но платформа предоставляет достаточно инструментов для эффективного обхода этого ограничения.