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