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

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

1С: как проверить значение на NULL

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

NULL в 1С — это специальное значение, которое означает отсутствие данных. Оно появляется в результатах запросов при левых соединениях без совпадений, при обращении к реквизитам необязательных характеристик, при группировках с итогами и при работе с внешними источниками данных. Главная особенность NULL в том, что он не равен ничему, включая сам себя, поэтому обычное сравнение «= NULL» никогда не сработает.

Из-за этого начинающие разработчики часто пишут условия вида ГДЕ Таблица.Реквизит = NULL и получают пустой результат, не понимая причины. Правильная проверка выполняется оператором ЕСТЬ NULL в языке запросов и функцией ЗначениеЗаполнено() или сравнением с Неопределено — во встроенном языке, но это разные механизмы, которые нельзя путать.

Материал ниже разбирает все рабочие способы проверки на NULL: в тексте запроса, в коде модулей, при соединениях таблиц и при выводе данных в отчёты. Отдельно рассмотрены типичные ошибки и способы заменить NULL на осмысленное значение.

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

NULL — это не пустая строка, не ноль и не пустая ссылка. Это отдельное состояние «значение отсутствует», которое платформа 1С привносит в результат запроса в нескольких типовых ситуациях. Понимание источников NULL помогает заранее предвидеть, где проверка обязательна.

Чаще всего NULL возникает при левом соединении: если для строки левой таблицы не нашлось пары в правой, все поля правой таблицы в этой строке будут NULL. Аналогично при правом соединении NULL появляется в полях левой таблицы, а при полном соединении — с обеих сторон там, где совпадений нет.

Второй источник — обращение к реквизитам через точку от поля составного типа или от ссылки, у которой такого реквизита нет. Третий — итоги и группировки: поля, не входящие в группировку и не агрегируемые, в итоговых записях дают NULL. Наконец, NULL приходит из внешних источников данных и при различии типов в объединениях запросов.

СоединенияЛЕВОЕ / ПРАВОЕ / ПОЛНОЕ

Нет совпадения по условию связи — поля второй таблицы равны NULL

Обращение через точкуСсылка.Реквизит

У объекта нет такого реквизита или ссылка битая

Группировки и итогиСГРУППИРОВАТЬ ПО, ИТОГИ

Неагрегированные поля в итоговых записях дают NULL

ОбъединенияОБЪЕДИНИТЬ

Поля, отсутствующие в одной из частей объединения, дают NULL

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

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

ВЫБРАТЬ

Товары.Номенклатура КАК Номенклатура,

Остатки.Количество КАК Количество

ИЗ

Справочник.Номенклатура КАК Товары

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

ПО Товары.Ссылка = Остатки.Номенклатура

ГДЕ

Остатки.Количество ЕСТЬ NULL

Такой запрос вернёт все товары, по которым вообще нет записей в таблице остатков. Обратное условие — «значение существует» — записывается с отрицанием: НЕ Остатки.Количество ЕСТЬ NULL. Скобки здесь не обязательны, но в сложных условиях с И/ИЛИ их лучше ставить явно, чтобы не ошибиться в приоритете.

Проверку ЕСТЬ NULL можно использовать не только в секции ГДЕ, но и в выражении ВЫБОР, чтобы формировать признак прямо в выборке:

ВЫБОР

КОГДА Остатки.Количество ЕСТЬ NULL

ТОГДА "Нет на складе"

ИНАЧЕ "В наличии"

КОНЕЦ КАК Статус

Замена NULL на значение: функция ЕСТЬNULL()

На практике чаще требуется не отфильтровать строки с NULL, а подставить вместо NULL рабочее значение — ноль, пустую строку или текст-заглушку. Для этого служит функция ЕСТЬNULL(Выражение, ЗначениеЗамены). Она возвращает первый аргумент, если он не NULL, иначе — второй аргумент.

ВЫБРАТЬ

Товары.Номенклатура КАК Номенклатура,

ЕСТЬNULL(Остатки.Количество, 0) КАК Количество

ИЗ

Справочник.Номенклатура КАК Товары

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

ПО Товары.Ссылка = Остатки.Номенклатура

Здесь у товаров без остатков в поле «Количество» будет 0, а не NULL — это позволяет безопасно суммировать колонку, сортировать по ней и сравнивать значения. Без замены арифметика с NULL дала бы NULL в результате, а сортировка и итоги вели бы себя неочевидно.

Ограничение функции: оба аргумента должны быть совместимы по типу. Нельзя написать ЕСТЬNULL(Остатки.Количество, "нет") — число и строка несовместимы, конструктор запроса или платформа сообщит об ошибке. Если нужен текстовый результат, сначала приведите число через ВЫБОР или представление.

bsl
ЕСТЬNULL(Остатки.Количество, 0) КАК Количество

Проверка NULL во встроенном языке 1С

Когда результат запроса обходит в коде модуля, значение NULL из выборки сравнивается напрямую с ключевым словом NULL — оно доступно и во встроенном языке:

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

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

Если Выборка.Количество = NULL Тогда

Сообщить("По товару " + Выборка.Номенклатура + " нет данных об остатках");

Иначе

// работаем со значением

КонецЕсли;

КонецЦикла;

В отличие от языка запросов, здесь сравнение = NULL работает корректно, потому что это уже не запрос, а обычное сравнение значений встроенного языка. Однако важно не путать NULL с Неопределено: Неопределено — это значение по умолчанию для неинициализированных переменных и параметров, а NULL приходит только из запросов и внешних источников. Проверка Значение = Неопределено не отловит NULL и наоборот.

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

Чем проверять в коде

= NULL

Точная проверка: отличает NULL от нуля и пустой строки. Подходит, когда важна семантика «данных нет»

ЗначениеЗаполнено()

Универсальная проверка на любую «пустоту»: NULL, Неопределено, 0, пустая строка, пустая ссылка. Не различает вид пустоты

= Неопределено

Только для переменных и параметров, не присвоенных явно. NULL из запроса этой проверкой не ловится

NULL при соединениях: типовые сценарии и ловушки

Самый массовый сценарий работы с NULL — левое соединение справочника с регистром. Разработчик хочет получить полный список товаров с остатками, включая нулевые, и правильно пишет ЛЕВОЕ СОЕДИНЕНИЕ. Но дальше начинаются различия в зависимости от того, что требуется получить.

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

Отдельная ловушка — условия по полям правой таблицы в секции ГДЕ. Если написать ГДЕ Остатки.Склад = &Склад, то для строк с NULL это условие не выполнится (NULL не равен складу), и левое соединение фактически превратится во внутреннее: товары без остатков выпадут из результата. Правильное место для такого условия — секция ПО самого соединения:

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

ПО Товары.Ссылка = Остатки.Номенклатура

И Остатки.Склад = &Склад

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

NULL в группировках, итогах и СКД

При группировке с секцией ИТОГИ в итоговых записях все детальные поля, не входящие в группировку, равны NULL. При обходе результата с типом обхода ПоГруппировкам это нужно учитывать: попытка вывести детальное поле из итоговой записи даст NULL, и конкатенация со строкой может привести к неожиданному результату или ошибке преобразования.

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

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

Порядок действий при подозрении на NULL
  1. 1
    Определите источник: соединение, обращение через точку, итоги или объединение
  2. 2
    Решите, что нужно: отфильтровать строки (ЕСТЬ NULL в ГДЕ) или заменить значение (ЕСТЬNULL в полях)
  3. 3
    Проверьте, что условия по правой таблице стоят в секции ПО, а не в ГДЕ
  4. 4
    Выполните запрос в консоли запросов и проверьте строки, где раньше были пропуски
  5. 5
    В коде обхода выборки добавьте обработку NULL или убедитесь, что запрос уже вернул чистые значения

Проверка результата и границы самостоятельной работы

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

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

Если запрос входит в типовой механизм конфигурации на поддержке, предпочтительнее не править типовой модуль, а обработать NULL в расширении или в собственной обёртке — это упростит будущие обновления конфигурации.

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

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

Строки левого соединения
Норма

Все записи левой таблицы присутствуют, в полях правой — NULL или замена

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

Часть записей левой таблицы пропала — условие ошибочно в ГДЕ

Арифметика с полями
Норма

Суммы и выражения дают числа

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

Результат выражения пустой — в расчёте участвовал NULL

Обход выборки в коде
Норма

Ветка «= NULL» срабатывает на строках без данных

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

Проверка на Неопределено не ловит NULL — перепутаны значения

Итог

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

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

Частые вопросы

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

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

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

NULL — это отсутствие значения в результатах запросов и внешних источников данных. Неопределено — значение по умолчанию для неинициализированных переменных, параметров и реквизитов составного типа во встроенном языке. Они не равны друг другу, и проверка одного не отлавливает другое.

Как вывести ноль вместо NULL в отчёте?

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

Почему левое соединение ведёт себя как внутреннее?

Скорее всего, условие по полю правой таблицы записано в секции ГДЕ. Для строк без совпадения это поле равно NULL, условие не выполняется, и строка отбрасывается. Перенесите условие в секцию ПО соединения — тогда фильтр применится до подстановки NULL.

Можно ли проверить на NULL сразу несколько полей?

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

Что вернёт ЕСТЬNULL, если оба аргумента NULL?

Функция вернёт второй аргумент, то есть NULL. Если нужна гарантированная подстановка, вторым аргументом должно быть конкретное значение подходящего типа — 0, пустая строка или пустая ссылка.