Разработка и Конфигурация · 8 мин
Как проверить значение на NULL и НЕОПРЕДЕЛЕНО в запросе 1С
Способы проверки значений NULL и НЕОПРЕДЕЛЕНО в запросах 1С: ЕСТЬ NULL, ЕСТЬNULL, сравнение с НЕОПРЕДЕЛЕНО, типичные ошибки и готовые примеры кода.
Проверка на неопределённое значение — одна из самых частых задач при написании запросов в 1С. Проблема в том, что в платформе существует два похожих, но принципиально разных понятия: NULL — отсутствие значения в результате соединения таблиц, и НЕОПРЕДЕЛЕНО — специальное значение, которое может храниться в реквизите составного типа. Путаница между ними приводит к ошибкам «Невозможно сравнить поля» и к некорректным данным в отчётах.
Обычное сравнение «равно / не равно» с NULL в запросе не работает: любая операция сравнения с NULL возвращает не ИСТИНА и не ЛОЖЬ, а NULL, поэтому условие ГДЕ Товары.Поставщик = NULL не вернёт ни одной строки. Для корректной проверки язык запросов 1С предоставляет специальные конструкции — оператор ЕСТЬ NULL и функцию ЕСТЬNULL().
Ниже разобраны оба сценария: работа с NULL после левых соединений и проверка значения НЕОПРЕДЕЛЕНО в полях составного типа, а также типичные ошибки и способы контроля результата.
Чем NULL отличается от НЕОПРЕДЕЛЕНО
NULL — это не значение, а признак отсутствия данных. Он появляется в результате запроса, когда при левом соединении для строки основной таблицы не нашлось пары в присоединяемой таблице: поля второй таблицы в такой строке будут содержать NULL. Также NULL возникает при обращении к реквизитам, которых нет у конкретного вида документа в выборке по журналу или при обращении через точку к ссылке составного типа.
НЕОПРЕДЕЛЕНО — это вполне конкретное значение, которое платформа записывает в реквизит составного типа, когда пользователь или код явно очистил поле. Оно хранится в базе данных и участвует в сравнениях как обычное значение. Пустая ссылка справочника — тоже не NULL и не НЕОПРЕДЕЛЕНО, а отдельное значение, проверяемое через ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка).
Проверка на NULL через оператор ЕСТЬ NULL
Основной способ отбора строк с отсутствующими данными — предикат ЕСТЬ NULL (в английском синтаксисе IS NULL). Он пишется после имени поля без знака равенства:
ГДЕ
Продажи.Менеджер ЕСТЬ NULL
Для обратного условия — отобрать только строки, где данные есть, — используется отрицание НЕ:
ГДЕ
НЕ Продажи.Менеджер ЕСТЬ NULL
Типичный сценарий — поиск документов, для которых нет связанных записей. Например, нужно найти заказы без оплат: выполняется левое соединение с таблицей оплат, и отбираются строки, где ключевое поле второй таблицы равно NULL.
ВЫБРАТЬ
Заказы.Ссылка КАК Заказ
ИЗ
Документ.ЗаказПокупателя КАК Заказы
ЛЕВОЕ СОЕДИНЕНИЕ Документ.ОплатаОтПокупателя КАК Оплаты
ПО Заказы.Ссылка = Оплаты.Заказ
ГДЕ
Оплаты.Ссылка ЕСТЬ NULLЗамена NULL значением по умолчанию через ЕСТЬNULL()
Часто NULL нужно не отфильтровать, а заменить осмысленным значением, чтобы отчёт не показывал пустые ячейки и чтобы вычисления не ломались. Для этого служит функция ЕСТЬNULL(ПроверяемоеПоле, ЗначениеЕслиNULL). Она возвращает поле, если оно не NULL, либо второй аргумент.
Классический пример — остатки по регистру при левом соединении со справочником номенклатуры. Если остатка нет, вместо NULL выводится ноль, и суммирование в итогах работает корректно:
ВЫБРАТЬ
Товары.Ссылка КАК Номенклатура,
ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток
ИЗ
Справочник.Номенклатура КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
ПО Товары.Ссылка = Остатки.Номенклатура
Важное ограничение: оба аргумента функции должны иметь совместимые типы. Если поле числовое, вторым аргументом нельзя передать строку — запрос завершится ошибкой. Для ссылочных полей типичная замена — пустая ссылка соответствующего типа через функцию ЗНАЧЕНИЕ().
Проверка на значение НЕОПРЕДЕЛЕНО
Значение НЕОПРЕДЕЛЕНО сравнивается обычными операторами, потому что оно реально хранится в базе. Отбор выглядит так:
ГДЕ
Контрагенты.Регион = НЕОПРЕДЕЛЕНО
Такая ситуация возникает в реквизитах составного типа, когда полю присвоили «очищенное» состояние. На практике проверка на НЕОПРЕДЕЛЕНО часто комбинируется с проверкой на пустую ссылку, поскольку пользователь мог и очистить поле, и оставить в нём пустую ссылку справочника.
Если в одном запросе встречаются оба случая — NULL от соединения и НЕОПРЕДЕЛЕНО из данных, — условия складывают через ИЛИ:
ГДЕ
Данные.Поле ЕСТЬ NULL
ИЛИ Данные.Поле = НЕОПРЕДЕЛЕНО
ИЛИ Данные.Поле = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)
Конструкция ВЫБОР для сложных условий
Когда нужно не отфильтровать строки, а пометить их или подставить разные значения в зависимости от состояния поля, используется оператор ВЫБОР — аналог CASE из классического SQL. Он позволяет в одном выражении обработать и NULL, и НЕОПРЕДЕЛЕНО, и пустую ссылку:
ВЫБОР
КОГДА Остатки.КоличествоОстаток ЕСТЬ NULL
ТОГДА 0
КОГДА Остатки.КоличествоОстаток < 0
ТОГДА 0
ИНАЧЕ Остатки.КоличествоОстаток
КОНЕЦ КАК Остаток
Ветка ИНАЧЕ обязательна, если хотя бы теоретически возможна ситуация, не покрытая условиями, — иначе для таких строк результатом выражения снова станет NULL, и проблема вернётся на следующем уровне обработки.
- 1Выполните запрос в консоли запросов без отборов и посмотрите, что реально приходит в проблемном поле: пустая ячейка (NULL), «<Неопределено>» или пустая ссылка
- 2Определите источник: NULL — ищите левое соединение или обращение к несуществующему реквизиту; НЕОПРЕДЕЛЕНО — проверяйте составной тип поля
- 3Для NULL добавьте ЕСТЬ NULL в отбор или ЕСТЬNULL в список полей; для НЕОПРЕДЕЛЕНО — обычное сравнение
- 4Повторно выполните запрос и проверьте, что количество строк и итоги соответствуют ожиданию
Проверка результата и контрольные точки
После изменения запроса результат стоит проверить в консоли запросов или в отладчике, сравнив количество строк до и после добавления условия. Если фильтр по NULL не сократил выборку вообще, возможно, NULL в данных нет, и проблема была в другом — например, в пустых ссылках.
Дополнительный приём — временно вывести само проверяемое поле в результат запроса и посмотреть, как платформа отображает его значения. NULL обычно показывается как пустая ячейка без типа, НЕОПРЕДЕЛЕНО — с явной подписью, пустая ссылка — с типом справочника или документа.
Как проверить результат
Отбираются условием ЕСТЬ NULL или заменяются ЕСТЬNULL
Условие «= NULL» — строки не возвращаются вообще
Суммы считаются, вместо пропусков стоят нули
Итоги занижены или содержат пропуски из-за NULL
Обработаны и НЕОПРЕДЕЛЕНО, и пустая ссылка
Проверяется только один вариант, часть данных теряется
Частые вопросы
Что важно запомнить
NULL и НЕОПРЕДЕЛЕНО — разные сущности. NULL проверяется только через ЕСТЬ NULL и заменяется функцией ЕСТЬNULL, НЕОПРЕДЕЛЕНО — обычным сравнением. Сравнение с NULL через «=» — самая частая и самая коварная ошибка, потому что запрос не сообщает об ошибке, а просто возвращает пустой результат.
Почему условие «ГДЕ Поле = NULL» не работает?
Потому что NULL — не значение, а отсутствие значения. Любое сравнение с NULL даёт неопределённый результат, и строка не проходит фильтр. Используйте «Поле ЕСТЬ NULL» или «НЕ Поле ЕСТЬ NULL».
Чем заменить NULL в числовом поле, чтобы итоги считались?
Функцией ЕСТЬNULL(Поле, 0). Тогда отсутствующие значения превратятся в нули, и суммирование в группировках и итогах отчёта будет корректным.
Как проверить поле одновременно на NULL и на пустую ссылку?
Объедините условия через ИЛИ: «Поле ЕСТЬ NULL ИЛИ Поле = ЗНАЧЕНИЕ(Справочник.ИмяСправочника.ПустаяСсылка)». Либо сначала оберните поле в ЕСТЬNULL с подстановкой пустой ссылки и сравнивайте уже результат.
Можно ли использовать ЕСТЬNULL для значения НЕОПРЕДЕЛЕНО?
Нет. ЕСТЬNULL реагирует только на NULL. Для НЕОПРЕДЕЛЕНО используйте конструкцию ВЫБОР КОГДА Поле = НЕОПРЕДЕЛЕНО ТОГДА ... ИНАЧЕ Поле КОНЕЦ.
Откуда берётся NULL, если соединений в запросе нет?
NULL появляется при обращении через точку к реквизиту ссылки составного типа, если у фактического объекта такого реквизита нет, а также при обращении к реквизиту документа в выборке по журналу, где этот реквизит определён не для всех видов документов.