Как правильно вывести и проверить пустые значения в запросе 1С?

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом
← На главную

При написании запросов в 1С начинающие (и даже опытные) разработчики часто сталкиваются с ситуацией, когда фильтрация по пустым значениям не срабатывает. В этой статье мы подробно разберем, почему конструкция ГДЕ Поле = NULL не имеет смысла, в чем разница между NULL и «Пустой ссылкой», и как правильно выводить пустые значения в отчеты и временные таблицы.

Анализ типичной ошибки в запросе

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


ГДЕ ВТ_НачисленияИОсновныеПоказатели.Действие = ЗНАЧЕНИЕ(Перечисление.ДействияСНачислениямиИУдержаниями.Утвердить) 
ИЛИ ВТ_НачисленияИОсновныеПоказатели.Действие = NULL

В данном коде заложены сразу две фундаментальные ошибки. Во-первых, использование оператора равенства с NULL. Во-вторых, непонимание того, что именно хранится в физических таблицах базы данных 1С.

Разберем по шагам: NULL против Пустой ссылки

В системе 1С:Предприятие важно четко разделять эти два понятия, так как они обрабатываются платформой совершенно по-разному:

  1. NULL — это полное отсутствие значения. В 1С NULL практически никогда не хранится в реквизитах физических таблиц (справочников или документов). Он возникает «на лету» в результате выполнения запроса, чаще всего при использовании ЛЕВОЕ СОЕДИНЕНИЕ, когда в правой таблице не найдено соответствующей записи.
  2. Пустая ссылка — это специальное значение ссылочного типа, которое указывает, что объект не выбран, но сам тип данных определен. Например, если в документе не выбрано подразделение, там хранится «Пустая ссылка» типа СправочникСсылка.ПодразделенияОрганизаций, а не NULL.

Важный вывод: Поле Действие, являющееся перечислением, в табличной части документа никогда не будет равно NULL. Оно может быть либо заполнено конкретным значением перечисления, либо содержать пустую ссылку этого перечисления.

Правильная проверка на пустоту в секции ГДЕ

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


ГДЕ Таблица.Действие = ЗНАЧЕНИЕ(Перечисление.ДействияСНачислениямиИУдержаниями.ПустаяСсылка)

Если же ваше поле действительно может содержать NULL (например, оно пришло из правой таблицы при левом соединении), то проверку нужно выполнять только через оператор ЕСТЬ NULL:

ГДЕ Таблица.Действие ЕСТЬ NULL

Универсальный и самый безопасный способ, который учитывает обе ситуации (и отсутствие записи в соединении, и незаполненный реквизит), выглядит так:


ГДЕ (Таблица.Действие ЕСТЬ NULL) 
ИЛИ (Таблица.Действие = ЗНАЧЕНИЕ(Перечисление.ДействияСНачислениямиИУдержаниями.ПустаяСсылка))

Почему сравнение «= NULL» всегда возвращает Ложь?

Выясним причину, по которой конструкция Поле = NULL не работает. Язык запросов 1С базируется на стандартах SQL, где используется трехзначная логика. Результатом любого сравнения с NULL (будь то равенство, неравенство или сравнение на «больше-меньше») всегда будет NULL, что в логическом условии трактуется как Ложь. Даже выражение NULL = NULL вернет Ложь. Поэтому запомните: для проверки на NULL используйте только ЕСТЬ NULL.

Использование функции ЕСТЬNULL для замены значений

Рассмотрим ситуацию, когда нам нужно не отфильтровать пустые значения, а заменить их на что-то конкретное прямо в выборке. Для этого идеально подходит функция ЕСТЬNULL. Посмотрим на пример:


ВЫБРАТЬ
    ЕСТЬNULL(КадровыйПереводПоказатели.Значение, 0) КАК ЗначениеПоказателя
ИЗ
    ВТ_Начисления КАК ВТ_Начисления
    ЛЕВОЕ СОЕДИНЕНИЕ Документ.КадровыйПеревод.Показатели КАК КадровыйПереводПоказатели
    ПО ВТ_Начисления.Ссылка = КадровыйПереводПоказатели.Ссылка

В данном случае, если в правой таблице показателей не будет найдено соответствие, вместо системного NULL в колонку ЗначениеПоказателя запишется число 0. Это позволяет избежать ошибок при последующих математических операциях в коде или в компоновке данных.

Искусственный вывод пустой колонки с типом

Иногда требуется создать в запросе пустую колонку определенного типа, чтобы позже заполнить её программно в таблице значений или в наборе данных. Просто написать NULL КАК МоеПоле недостаточно, так как платформа не поймет, какой тип данных там должен быть.

Проанализируем два способа типизации:

  1. Для ссылочных типов: Используйте функцию ЗНАЧЕНИЕ.
    ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка) КАК Номенклатура
  2. Для произвольных типов через NULL: Используйте конструкцию ВЫРАЗИТЬ.
    ВЫРАЗИТЬ(NULL КАК Справочник.Контрагенты) КАК Контрагент

Ловушка Левого соединения: когда оно превращается во Внутреннее

Это критическая ошибка, которую часто допускают при попытке «вывести пустые значения». Если вы выполняете ЛЕВОЕ СОЕДИНЕНИЕ, ожидая получить все строки из левой таблицы (даже если для них нет данных справа), но затем в секции ГДЕ ставите условие на поле из ПРАВОЙ таблицы — ваше левое соединение превращается во внутреннее.

Пример ошибки:


ВЫБРАТЬ ...
ИЗ ВТ_Начисления КАК Левая
ЛЕВОЕ СОЕДИНЕНИЕ Документ.Показатели КАК Правая ПО Левая.ИД = Правая.ИД
ГДЕ Правая.Значение > 0

В этом случае все строки, где Правая.Значение было NULL (не нашлось соответствия), будут отсечены условием > 0. Чтобы этого избежать, перенесите условие из ГДЕ в секцию ПО:


ВЫБРАТЬ ...
ИЗ ВТ_Начисления КАК Левая
ЛЕВОЕ СОЕДИНЕНИЕ Документ.Показатели КАК Правая 
    ПО Левая.ИД = Правая.ИД 
    И Правая.Значение > 0

Теперь запрос вернет все строки из левой таблицы, а данные из правой подтянутся только при соблюдении обоих условий. Для интерактивной отладки и проверки таких конструкций можно использовать инженерную консоль запросов для 1С.

← На главную