При написании запросов в платформе 1С:Предприятие часто возникает задача получить значение реквизита объекта, ссылка на который передается в запрос в виде параметра. Прямая попытка обратиться к полю через точку, например &СсылкаНаЭлемент.Код, приводит к синтаксической ошибке, так как механизм синтаксического анализа запросов не знает точный тип данных переданного параметра.
Разберем по шагам, почему возникает эта ошибка, какие существуют способы разыменования параметров в тексте запроса и какие рекомендации по производительности следует соблюдать.
Для того чтобы парсер и визуальный Конструктор запросов поняли, к какому именно метаданному объекту относится параметр, необходимо явно типизировать его с помощью функции ВЫРАЗИТЬ. Это документированный и рекомендуемый стандарт платформы 1С.
Посмотрим на пример правильного синтаксиса:
ВЫБРАТЬ
ВЫРАЗИТЬ(&СсылкаНаЭлемент КАК Справочник.Номенклатура).Код КАК Код,
ВЫРАЗИТЬ(&СсылкаНаЭлемент КАК Справочник.Номенклатура).Артикул КАК Артикул
Данную конструкцию можно использовать не только в списке выборки, но и в секции условий ГДЕ:
ВЫБРАТЬ
Спр.Ссылка КАК Ссылка
ИЗ
Справочник.Валюты КАК Спр
ГДЕ
Спр.Код <> ВЫРАЗИТЬ(&СсылкаНаЭлемент КАК Справочник.Валюты).Код
Преимущества данного подхода:
Проанализируем альтернативный вариант, с которым иногда сталкиваются разработчики:
ВЫБРАТЬ
Спр.Ссылка КАК Ссылка
ИЗ
Справочник.Валюты КАК Спр
ГДЕ
Спр.Код <> (&Ссылка).Код
Особенности этого способа:
(&Ссылка).Код является недокументированной особенностью парсера СУБД. В ряде релизов платформы такой запрос может успешно выполниться на сервере.(&Ссылка).Реквизит в рабочих решениях крайне не рекомендуется.Разберем поведение платформы при выполнении запроса в нестандартных ситуациях:
Неопределено, NULL или ссылка другого типа (например, документ вместо справочника), результатом выражения ВЫРАЗИТЬ(...).Реквизит будет значение NULL.ГДЕ или в арифметических операциях рекомендуется оборачивать выражение в функцию ЕСТЬNULL, чтобы избежать непредвиденной фильтрации данных:
ВЫБРАТЬ
Спр.Ссылка КАК Ссылка
ИЗ
Справочник.Номенклатура КАК Спр
ГДЕ
Спр.Артикул = ЕСТЬNULL(ВЫРАЗИТЬ(&ВыбТовар КАК Справочник.Номенклатура).Артикул, "")
Выясним, как платформа обрабатывает разыменование параметров на уровне СУБД:
ВЫРАЗИТЬ(&Параметр КАК ...).Реквизит платформа строит неявное левое соединение (LEFT JOIN) или скалярный подзапрос к таблице соответствующего объекта.Для оптимизации производительности рекомендуем следующие альтернативы:
ОбщегоНазначения.ЗначениеРеквизитаОбъекта) и передать в запрос простым скалярным типом (число, строка):
Запрос.УстановитьПараметр("ИскомыйКод", СсылкаНаЭлемент.Код);
ЛЕВОЕ СОЕДИНЕНИЕ с таблицей справочника или документа по условию равенства ссылки параметру.