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