К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как сравнить значение с NULL в 1С

Как правильно сравнить значение с NULL в запросах и коде 1С: оператор ЕСТЬ NULL, ЕСТЬNULL(), типичные ошибки при сравнении и проверка результата запроса.

В языке запросов 1С и во встроенном языке платформы значение NULL ведёт себя не так, как обычные типы данных. Прямое сравнение через знак равенства с NULL никогда не даст «Истина»: результатом такого сравнения будет сам NULL, то есть «неизвестно». Из-за этого условие вроде «Поле = NULL» просто отфильтрует все строки, и разработчик получает пустую выборку без каких-либо сообщений об ошибке.

Правильный инструмент для проверки на NULL в запросах — оператор ЕСТЬ NULL (IS NULL), а для замены NULL на конкретное значение — функция ЕСТЬNULL() (ISNULL). Во встроенном языке, вне запросов, используется сравнение с Неопределено или проверка на пустое значение через ЗначениеЗаполнено(). Путаница между этими механизмами — одна из самых частых причин «потерянных» записей в отчётах.

NULL в 1С возникает в строго определённых ситуациях: при левом соединении таблиц, когда в присоединяемой таблице нет подходящей строки, при обращении к реквизитам через точку от «битой» ссылки, при агрегации пустых наборов. Понимание источника NULL помогает выбрать верный способ проверки и не маскировать ошибки в логике запроса.

Что такое NULL в 1С и откуда он берётся

NULL — это отсутствие значения, а не пустая строка, не ноль и не пустая ссылка. Это принципиально важно: пустая строка «» и NULL — разные состояния. Поле может содержать пустую строку и при этом не быть NULL, и наоборот. Сравнение «Поле = """"» не найдёт записи, где поле равно NULL, и наоборот.

На практике NULL чаще всего появляется в трёх случаях. Первый — левое соединение: если для строки основной таблицы не нашлось пары в присоединяемой, все поля присоединяемой таблицы будут NULL. Второй — обращение через точку к реквизиту «битой» ссылки (объект удалён, а ссылка осталась): выражение вида «Товары.Номенклатура.Артикул» вернёт NULL. Третий — агрегатные функции над пустым набором или соединение с виртуальными таблицами без данных.

Как проверить на NULL в запросе: оператор ЕСТЬ NULL

Единственный корректный способ отобрать строки, где поле не заполнено — конструкция ГДЕ Поле ЕСТЬ NULL. Для обратного отбора используется ГДЕ НЕ Поле ЕСТЬ NULL либо ГДЕ Поле ЕСТЬ NULL = Ложь, хотя первый вариант читается лучше. Оператор работает с полями любого типа: ссылками, числами, строками, датами.

// Отобрать документы, для которых нет строк в таблице оплат

ВЫБРАТЬ

Заказы.Ссылка КАК Заказ,

Оплаты.Сумма КАК СуммаОплаты

ИЗ

Документ.ЗаказКлиента КАК Заказы

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Оплаты КАК Оплаты

ПО Заказы.Ссылка = Оплаты.Заказ

ГДЕ

Оплаты.Сумма ЕСТЬ NULL

Обратите внимание: проверять нужно поле именно присоединяемой таблицы, а не поле связи из основной таблицы — оно заполнено всегда. Если проверить «Заказы.Ссылка ЕСТЬ NULL», выборка будет пустой, потому что ссылка на документ существует по определению.

Как найти строки с NULL после левого соединения
  1. 1
    Определите, какая таблица в соединении присоединяемая (правая в ЛЕВОМ СОЕДИНЕНИИ)
  2. 2
    Выберите поле из этой таблицы, которое заполнено в каждой реальной записи, например ключ или ссылку
  3. 3
    Добавьте условие ГДЕ ПолеПрисоединяемойТаблицы ЕСТЬ NULL
  4. 4
    Выполните запрос в консоли запросов и убедитесь, что вернулись именно строки без пары
  5. 5
    Для обратной задачи замените условие на НЕ Поле ЕСТЬ NULL

Функция ЕСТЬNULL(): замена NULL на рабочее значение

Когда NULL нужно не отфильтровать, а заменить на осмысленное значение, применяется функция ЕСТЬNULL(Поле, ЗначениеЗамены). Типичный пример — вывод нуля вместо NULL для сумм и остатков, чтобы последующие вычисления и итоги работали корректно: ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток.

Функция принимает ровно два аргумента, и тип второго аргумента должен быть совместим с типом первого: нельзя подставить строку вместо числового поля без явного приведения. Для ссылочных полей часто подставляют пустую ссылку нужного типа: ЕСТЬNULL(Товары.Номенклатура, ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)).

Есть и обратный приём: функция ЕСТЬNULL позволяет сравнивать поля через обычное равенство, предварительно заменив NULL. Например, условие ГДЕ ЕСТЬNULL(Оплаты.Сумма, 0) = 0 отберёт и строки с нулевой оплатой, и строки без оплаты вовсе. Это удобно, когда бизнес-логика не различает эти два состояния.

ЕСТЬ NULL или ЕСТЬNULL()

Оператор ЕСТЬ NULL

Используется в условии ГДЕ для отбора строк с отсутствующим значением. Не изменяет данные, только фильтрует.

Функция ЕСТЬNULL()

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

Сравнение через ЕСТЬNULL в условии

Комбинированный приём: ГДЕ ЕСТЬNULL(Поле, 0) = 0. Требует осторожности, так как смешивает NULL и реальные нулевые значения.

Сравнение с NULL в коде встроенного языка

Вне запросов, в модуле, значение NULL как таковое почти не встречается — оно живёт внутри выборок и таблиц значений, полученных из запроса. Когда вы обходите результат запроса через Выборка.Следующий(), поля, содержавшие NULL, приходят именно как NULL, и проверить их можно оператором сравнения: Если Выборка.Сумма = NULL Тогда. Во встроенном языке такое сравнение работает корректно — это особенность платформы, отличающаяся от поведения NULL внутри текста запроса.

Не путайте NULL с Неопределено. Неопределено — значение встроенного языка, которое возвращают функции без возврата, несуществующие реквизиты и т.п. Проверка «Значение = NULL» для переменной, содержащей Неопределено, даст Ложь. Если источник данных неизвестен, безопаснее проверять оба варианта или использовать ЗначениеЗаполнено(), которая для NULL и Неопределено вернёт Ложь.

Запрос = Новый Запрос("ВЫБРАТЬ ... ЛЕВОЕ СОЕДИНЕНИЕ ...");

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл

Если Выборка.СуммаОплаты = NULL Тогда

СуммаОплаты = 0;

Иначе

СуммаОплаты = Выборка.СуммаОплаты;

КонецЕсли;

КонецЦикла;

Типичные ошибки при сравнении с NULL

Самая распространённая ошибка — написать ГДЕ Поле = NULL по аналогии с обычными значениями. Запрос выполнится без ошибки синтаксиса, но вернёт ноль строк, и поиск причины может занять много времени, особенно в большом запросе с несколькими соединениями.

Вторая частая проблема — сравнение полей двух таблиц, где одно из них может быть NULL. Условие вида ГДЕ Таблица1.Количество <> Таблица2.Количество не отберёт строки, где одно из полей NULL, хотя логически они «разные». Корректное решение — обернуть оба поля в ЕСТЬNULL с одинаковым значением замены, либо добавить явные проверки на NULL через ИЛИ.

Третья ошибка — проверка на NULL не того поля. После левого соединения разработчик проверяет поле основной таблицы, которое не может быть NULL, и получает пустой результат. Также опасно применять ЕСТЬNULL до соединения в надежде «застраховаться»: функция работает только с уже полученным результатом, а не предотвращает появление NULL.

Типичные ошибки
01
Условие «Поле = NULL» в тексте запроса — результат всегда пустой, замените на «Поле ЕСТЬ NULL»
02
Проверка поля основной таблицы после левого соединения — NULL появляется только в полях присоединяемой таблицы
03
Сравнение «<>» двух полей без учёта NULL — строки с NULL молча выпадают из выборки
04
Подстановка в ЕСТЬNULL значения несовместимого типа — ошибка исполнения запроса
05
Сравнение в коде «Значение = NULL», когда переменная содержит Неопределено — проверка не сработает

NULL в параметрах, соединениях и СКД

При передаче параметра в запрос учитывайте: если в параметр попало Неопределено, условие «Поле = &Параметр» не сработает ожидаемым образом. Перед установкой параметра проверяйте значение и при необходимости подставляйте пустую ссылку или NULL явно через Запрос.УстановитьПараметр("Парам", NULL).

В СКД (системе компоновки данных) проверки на NULL в вычисляемых полях и отборах пишутся на том же языке запросов: «ЕСТЬ NULL» доступен и в условиях отбора, если включить режим произвольного выражения. В ресурсах и итогах незаменённый NULL может приводить к пустым ячейкам вместо нулей, поэтому суммовые поля принято оборачивать в ЕСТЬNULL ещё в тексте запроса набора данных.

Отдельный случай — соединение с виртуальными таблицами регистров. Если срез последних или остатки не содержат записи по объекту, все поля виртуальной таблицы будут NULL. Для отчётов по остаткам всегда решайте осознанно: отфильтровать такие объекты через ЕСТЬ NULL или показать их с нулевыми значениями через ЕСТЬNULL.

Маршрут решения

Как выбрать способ обработки NULL

Нужно отобрать записи без пары в соединенииИспользуйте ГДЕ ПолеПрисоединяемойТаблицы ЕСТЬ NULL
NULL мешает расчётам и итогамОберните поле в ЕСТЬNULL(Поле, 0) или аналог с подходящим типом
Проверка выполняется в модуле после выборки запросаСравнивайте «Выборка.Поле = NULL» или используйте ЗначениеЗаполнено()
Источник значения неизвестен (NULL или Неопределено)Применяйте ЗначениеЗаполнено() — она одинаково обрабатывает оба состояния
Нужно сравнить два поля, где возможны NULLСравнивайте ЕСТЬNULL(Поле1, Замена) и ЕСТЬNULL(Поле2, Замена) с одинаковой заменой

Как проверить результат и убедиться в правильности запроса

Перед переносом запроса в код выполните его в консоли запросов на реальных данных и вручную найдите хотя бы одну запись, которая заведомо должна попасть под условие ЕСТЬ NULL. Если такая запись известна, но в результат не попала — условие составлено неверно, чаще всего проверяется не то поле.

Полезный приём — временно вывести само проверяемое поле в список выборки и посмотреть его значение глазами. NULL в табличном результате консоли обычно отображается как пустая ячейка, что отличается от нуля и пустой строки. Дополнительно сравните количество строк до и после добавления условия: резкое обнуление результата — признак ошибки «Поле = NULL».

Контрольные точки

Как проверить результат

Запрос с условием ЕСТЬ NULL
Норма

Возвращаются строки, где поле присоединяемой таблицы пустое

Тревожный признак

Пустой результат при заведомо существующих записях без пары

Поле с ЕСТЬNULL в выборке
Норма

Вместо пустых ячеек отображается значение замены (0, пустая ссылка)

Тревожный признак

Пустые ячейки остались — функция применена не к тому полю

Сравнение полей двух таблиц
Норма

Строки с NULL с одной стороны попадают в результат согласно логике

Тревожный признак

Строки с NULL молча исчезают из выборки

Проверка в модуле
Норма

«Выборка.Поле = NULL» возвращает Истина для пустых полей выборки

Тревожный признак

Условие не срабатывает — возможно, в переменной Неопределено, а не NULL

Часто задаваемые вопросы

Почему условие «Поле = NULL» не возвращает ни одной строки?

По правилам трёхзначной логики любое сравнение с NULL через «=» даёт неопределённый результат, а не Истину или Ложь. В условии ГДЕ неопределённый результат трактуется как отказ от строки, поэтому выборка пустеет. Используйте «Поле ЕСТЬ NULL» — это единственный корректный синтаксис в языке запросов 1С.

Чем NULL отличается от Неопределено?

NULL существует только внутри результатов запросов и означает отсутствие значения в поле. Неопределено — значение встроенного языка, которое получают переменные без присвоения и функции без возврата. В коде модуля их нужно проверять отдельно: «Значение = NULL» не сработает для Неопределено и наоборот.

Как заменить NULL на пустую ссылку нужного типа?

Используйте функцию ЕСТЬNULL с явным значением: ЕСТЬNULL(Поле, ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)). Тип замены должен совпадать с типом поля, иначе запрос завершится ошибкой. Для составных полей выбирайте тот тип, который ожидает дальнейшая логика.

Как сравнить два поля, если в обоих может быть NULL?

Оберните оба поля в ЕСТЬNULL с одинаковым значением замены: ГДЕ ЕСТЬNULL(Т1.Поле, 0) = ЕСТЬNULL(Т2.Поле, 0). Учтите, что при этом пара «NULL и NULL» будет считаться равной, а пара «NULL и реальный ноль» — тоже равной. Если такие случаи нужно различать, добавьте явные проверки ЕСТЬ NULL через ИЛИ.

Работает ли ЕСТЬ NULL в отборах динамического списка и СКД?

Да, в произвольных выражениях отбора СКД и в условиях динамических списков оператор ЕСТЬ NULL доступен, так как там применяется тот же язык выражений запроса. В простых настройках отбора пользователя отдельного вида сравнения «NULL» нет — там используется «Не заполнено», что охватывает и пустые ссылки.

Почему в итогах отчёта пустые ячейки вместо нулей?

Это признак того, что суммируемое поле содержит NULL, обычно из-за левого соединения с виртуальной таблицей без записей. Агрегирование NULL даёт NULL, который в отчёте выглядит как пустота. Решение — обернуть поле в ЕСТЬNULL(Поле, 0) в тексте запроса набора данных до группировки.

Итог

Что важно запомнить

Сравнение с NULL в запросах 1С выполняется только оператором ЕСТЬ NULL, а не знаком равенства. Для подмены NULL используйте ЕСТЬNULL() с типосовместимым значением. В коде модуля различайте NULL и Неопределено, а для универсальных проверок применяйте ЗначениеЗаполнено(). Проверяйте запрос на контрольных данных до переноса в рабочий код.