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