Проверка на пустое значение в запросе 1С: NULL, пустая ссылка, дата
«Пусто» в запросе 1С — это три разных значения, и проверяются они по-разному.
NULL (нет данных, обычно после ЛЕВОЕ СОЕДИНЕНИЕ) — только через
оператор ЕСТЬ NULL / ЕСТЬ НЕ NULL, а не через =.
Пустая ссылка — через = ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка).
Пустая дата и строка — сравнением с параметром (&ПустаяДата) или с "".
Чтобы заменить NULL на осмысленное значение прямо в запросе, используйте функцию
ЕСТЬNULL(Поле, Замена) или конструкцию ВЫБОР КОГДА … ТОГДА … КОНЕЦ.
Во встроенном языке (не в запросе) универсальная проверка — глобальная функция
ЗначениеЗаполнено().
NULL, пустая ссылка и незаполненное значение — в чём разница
Главная причина, почему проверка на пустое значение в запросе 1С «не срабатывает» — три разных состояния путают между собой:
-
NULL — данных физически нет. Появляется при
ЛЕВОЕ СОЕДИНЕНИЕ, когда справа нет соответствия, а также при обращении к реквизитам, которых нет у объекта (реквизиты элемента у группы справочника и наоборот). - Пустая ссылка — значение ссылочного типа есть, но не заполнено (например, поле «Контрагент» осталось незаполненным). Это не NULL.
-
Пустая дата и пустая строка — примитивные типы со значением по умолчанию:
'00010101000000'и"".
Ключевой момент: NULL нельзя сравнивать через =. Условие
Поле = NULL всегда даёт неопределённый результат и не отбирает строки. Для NULL есть
отдельный оператор, для пустой ссылки — своя конструкция. Разберём по порядку.
Проверка на NULL: оператор ЕСТЬ NULL и ЕСТЬ НЕ NULL
Отобрать строки, где значение равно NULL, позволяет логический оператор языка запросов
ЕСТЬ NULL. Обратная проверка — ЕСТЬ НЕ NULL. Классический сценарий —
найти элементы, по которым нет данных в присоединённой таблице:
ВЫБРАТЬ
Товары.Ссылка КАК Товар
ИЗ
Справочник.Номенклатура КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
ПО Остатки.Номенклатура = Товары.Ссылка
ГДЕ
Остатки.Номенклатура ЕСТЬ NULL // товары без остатков на складе
Оператор работает и в секции ГДЕ, и внутри ВЫБОР КОГДА. Не путайте его
с функцией ЕСТЬNULL() (о ней ниже): ЕСТЬ NULL — это проверка,
возвращающая Истина/Ложь, а ЕСТЬNULL() — замена значения.
Функция ЕСТЬNULL: замена пустого значения в запросе
Когда NULL нужно не отобрать, а заменить на осмысленное значение (0 для сумм,
пустую строку для текста), используют функцию ЕСТЬNULL(Поле, Замена). Она возвращает
первый аргумент, если он не равен NULL, иначе — второй:
ВЫБРАТЬ
Товары.Ссылка КАК Товар,
ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток
ИЗ
Справочник.Номенклатура КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
ПО Остатки.Номенклатура = Товары.Ссылка
Без ЕСТЬNULL() сумма NULL + 100 в запросе даст NULL, а не
100 — любое арифметическое действие с NULL «обнуляет» результат. Поэтому заменяйте NULL до арифметики только тогда, когда по смыслу отсутствующее значение действительно равно нулю.
ЕСТЬNULL: тип замены и положение относительно СУММА
Руководство 8.3.27, §8.4.17.4.11, и методика ИТС описывают приведение замены к строковому или числовому типу первого аргумента. Не используйте ЕСТЬNULL как универсальный способ расширить строку или разрядность числа. При необходимости явно задайте требуемый тип выражения и проверьте результат на целевой платформе и СУБД.
Руководство описывает приведение замены к строковому или числовому типу первого аргумента. Однако в проверенных сценариях файловой базы 8.3.27.1989, включая типизированное поле после левого соединения, замена не усеклась. Не рассчитывайте на ЕСТЬNULL как на средство принудительного ограничения длины; проверяйте нужный контекст отдельно.
// Замена после агрегата защищает итог пустой выборки.
ВЫБРАТЬ ЕСТЬNULL(СУММА(Данные.Количество), 0) КАК Количество
ИЗ ВТ_Данные КАК Данные
ЕСТЬNULL(СУММА(Поле), 0) и СУММА(ЕСТЬNULL(Поле, 0)) расположены на разных уровнях вычисления. Вторая форма заменяет значения существующих строк, но не создаёт строк в пустой исходной выборке. Решайте отдельно, означает ли NULL ноль или отсутствие наблюдения: для среднего такая замена изменит знаменатель.
Пустая ссылка в запросе: проверка через ЗНАЧЕНИЕ
Пустая ссылка в запросе 1С — это не NULL. У каждого ссылочного типа есть служебное значение
«пустая ссылка», и сравнивать поле нужно именно с ним — через оператор ЗНАЧЕНИЕ:
ВЫБРАТЬ
Заказы.Ссылка
ИЗ
Документ.ЗаказПокупателя КАК Заказы
ГДЕ
Заказы.Контрагент = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка) // не заполнен контрагент
Обратное условие «ссылка заполнена» — через <>:
ГДЕ
Заказы.Контрагент <> ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)
Альтернатива — передать пустую ссылку параметром из встроенного языка. Это удобно, когда тип определяется динамически:
Запрос.Текст =
"ВЫБРАТЬ Заказы.Ссылка
|ИЗ Документ.ЗаказПокупателя КАК Заказы
|ГДЕ Заказы.Контрагент = &ПустаяСсылка";
Запрос.УстановитьПараметр("ПустаяСсылка", Справочники.Контрагенты.ПустаяСсылка());
Внимание: для полей составного типа, где значение «ничего не выбрано»,
проверяйте фактическое значение: НЕОПРЕДЕЛЕНО или пустую ссылку допустимого типа. Составной тип не исключает хранения пустой ссылки.
Пустая дата и пустая строка в запросе (ДАТАВРЕМЯ(1, 1, 1) и &ПустаяДата)
Пустая дата в 1С хранится как минимальная дата начала эры 01.01.0001 00:00:00 ('00010101000000'). Проверить поле на пустую дату в секции ГДЕ или ВЫБОР КОГДА можно двумя равнозначными способами — через встроенный литерал языка запросов ДАТАВРЕМЯ(1, 1, 1) (удобно в СКД и динамических списках, где не нужно передавать параметр из кода) либо через параметр &ПустаяДата:
// Способ 1. Прямо в тексте запроса через литерал ДАТАВРЕМЯ(1, 1, 1)
ВЫБРАТЬ
Задачи.Ссылка КАК Задача
ИЗ
Задача.ЗадачаИсполнителя КАК Задачи
ГДЕ
Задачи.ДатаЗавершения = ДАТАВРЕМЯ(1, 1, 1) // дата не заполнена
// Способ 2. Через параметр из встроенного языка
// Запрос.УстановитьПараметр("ПустаяДата", Дата(1, 1, 1));
Если поле даты получено из присоединённой таблицы после ЛЕВОЕ СОЕДИНЕНИЕ, там может оказаться как пустая дата ДАТАВРЕМЯ(1, 1, 1), так и NULL. Чтобы отобрать обе ситуации одним условием, оберните поле в ЕСТЬNULL:
ГДЕ
ЕСТЬNULL(Оплаты.ДатаОплаты, ДАТАВРЕМЯ(1, 1, 1)) = ДАТАВРЕМЯ(1, 1, 1)
Пустая строка проверяется прямым сравнением с "". В языке запросов концевые пробелы при сравнении игнорируются, в отличие от BSL. СокрЛП имеет смысл для явного удаления начальных и конечных пробелов, но не является обязательным условием сравнения с пустой строкой:
ГДЕ
СокрЛП(Контрагенты.Комментарий) = "" // комментарий не заполнен
ВЫБОР КОГДА для замены NULL и пустых значений
Когда логика сложнее простой замены, помогает конструкция ВЫБОР КОГДА … ТОГДА … ИНАЧЕ … КОНЕЦ.
Она пригодится, чтобы одним полем показать статус заполненности:
ВЫБРАТЬ
Товары.Ссылка КАК Товар,
ВЫБОР
КОГДА Остатки.КоличествоОстаток ЕСТЬ NULL ТОГДА "Нет на складе"
КОГДА Остатки.КоличествоОстаток = 0 ТОГДА "Закончился"
ИНАЧЕ "В наличии"
КОНЕЦ КАК Статус
ИЗ
Справочник.Номенклатура КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
ПО Остатки.Номенклатура = Товары.Ссылка
Обратите внимание: сначала проверяем ЕСТЬ NULL (нет строки вообще), и только потом
= 0 (строка есть, но количество нулевое) — это два разных случая пустоты.
ЗначениеЗаполнено вне запроса: проверка результата
В самом языке запросов функции ЗначениеЗаполнено нет. Но во встроенном языке она —
универсальный способ проверить пустое значение после получения данных из выборки. Функция
считает пустыми пустую ссылку, пустую дату, пустую строку, а также NULL и
Неопределено:
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Если НЕ ЗначениеЗаполнено(Выборка.Контрагент) Тогда
Сообщить("У заказа " + Выборка.Ссылка + " не заполнен контрагент");
КонецЕсли;
КонецЦикла;
Это удобно для проверки «на выходе», но не заменяет отбор в запросе: если строк без значения
много, отфильтровать их условием ГДЕ … ЕСТЬ NULL или
= ЗНАЧЕНИЕ(…ПустаяСсылка) быстрее, чем перебирать всю выборку в цикле.
Частые ошибки при проверке на пустое значение в запросе 1С
-
Сравнение с NULL через
=. УсловиеПоле = NULLникогда не истинно и молча не отбирает строки. Для NULL — только операторЕСТЬ NULL/ЕСТЬ НЕ NULL. -
Путают NULL и пустую ссылку. После левого соединения приходит NULL,
а незаполненный реквизит в основной таблице — пустая ссылка. Это разные проверки:
ЕСТЬ NULLпротив= ЗНАЧЕНИЕ(…ПустаяСсылка). -
Забыли обернуть поле в
ЕСТЬNULL(). Любая арифметика с NULL даёт NULL — суммы и итоги «схлопываются». Подставляйте ноль только если это соответствует смыслу отсутствующего значения; для агрегатов отдельно проверьте пустой набор. -
Сравнение составного поля с пустой ссылкой. Для поля составного типа
возможны
НЕОПРЕДЕЛЕНОи пустая ссылка допустимого типа; различайте эти состояния. -
Проверка строки без
СокрЛП. Не переносите правила сравнения BSL в запрос: концевые пробелы при сравнении строк в запросе игнорируются. Для явной нормализации начала и конца строки используйтеСокрЛП.
Частые вопросы о проверке на пустое значение в запросе 1С
Почему условие Поле = NULL не работает в запросе 1С?
Потому что NULL нельзя сравнивать через =: результат такого сравнения всегда
неопределён, и строки не отбираются. Используйте оператор ЕСТЬ NULL для отбора
пустых значений и ЕСТЬ НЕ NULL — для заполненных.
Чем отличается ЕСТЬ NULL от функции ЕСТЬNULL?
ЕСТЬ NULL — это оператор-проверка: он возвращает Истина/Ложь и применяется
в секции ГДЕ или в ВЫБОР. ЕСТЬNULL(Поле, Замена) — это функция-замена:
она возвращает второй аргумент, если первый равен NULL, и используется в списке выбираемых полей.
Как проверить пустую ссылку в запросе 1С?
Сравнением с оператором ЗНАЧЕНИЕ:
Поле = ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка). Для поля составного типа
проверьте, хранится ли НЕОПРЕДЕЛЕНО или пустая ссылка допустимого типа.