Язык запросов 1С

Проверка на пустое значение в запросе 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()замена значения.

Функция ЕСТЬNULL: замена пустого значения в запросе

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

ВЫБРАТЬ
    Товары.Ссылка КАК Товар,
    ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток
ИЗ
    Справочник.Номенклатура КАК Товары
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
    ПО Остатки.Номенклатура = Товары.Ссылка
ЕСТЬNULL
Полепроверяемое выражение
Заменазначение, если Поле равно NULL
→ тип поля или замены

Без ЕСТЬNULL() сумма NULL + 100 в запросе даст NULL, а не 100 — любое арифметическое действие с NULL «обнуляет» результат. Поэтому все поля из левого соединения, участвующие в вычислениях и итогах, оборачивают в ЕСТЬNULL().

Пустая ссылка в запросе: проверка через ЗНАЧЕНИЕ

Пустая ссылка в запросе 1С — это не NULL. У каждого ссылочного типа есть служебное значение «пустая ссылка», и сравнивать поле нужно именно с ним — через оператор ЗНАЧЕНИЕ:

ВЫБРАТЬ
    Заказы.Ссылка
ИЗ
    Документ.ЗаказПокупателя КАК Заказы
ГДЕ
    Заказы.Контрагент = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)   // не заполнен контрагент

Обратное условие «ссылка заполнена» — через <>:

ГДЕ
    Заказы.Контрагент <> ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)

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

Запрос.Текст =
    "ВЫБРАТЬ Заказы.Ссылка
    |ИЗ Документ.ЗаказПокупателя КАК Заказы
    |ГДЕ Заказы.Контрагент = &ПустаяСсылка";
Запрос.УстановитьПараметр("ПустаяСсылка", Справочники.Контрагенты.ПустаяСсылка());

Внимание: для полей составного типа, где значение «ничего не выбрано», сравнивать нужно с НЕОПРЕДЕЛЕНО (Поле = НЕОПРЕДЕЛЕНО), а не с пустой ссылкой конкретного типа.

Пустая дата и пустая строка в запросе

Пустая дата в запросе — это дата по умолчанию '00010101000000'. Надёжнее всего сравнивать поле с параметром, куда передана пустая дата из встроенного языка:

Запрос.Текст =
    "ВЫБРАТЬ Задачи.Ссылка
    |ИЗ Задача.ЗадачаИсполнителя КАК Задачи
    |ГДЕ Задачи.ДатаЗавершения = &ПустаяДата";   // ещё не завершены
Запрос.УстановитьПараметр("ПустаяДата", '00010101000000');

Пустая строка проверяется прямым сравнением с "". Учтите, что строки из пробелов пустыми не считаются — при необходимости обрежьте их функцией СокрЛП:

ГДЕ
    СокрЛП(Контрагенты.Комментарий) = ""   // комментарий не заполнен

ВЫБОР КОГДА для замены NULL и пустых значений

Когда логика сложнее простой замены, помогает конструкция ВЫБОР КОГДА … ТОГДА … ИНАЧЕ … КОНЕЦ. Она пригодится, чтобы одним полем показать статус заполненности:

ВЫБРАТЬ
    Товары.Ссылка КАК Товар,
    ВЫБОР
        КОГДА Остатки.КоличествоОстаток ЕСТЬ NULL ТОГДА "Нет на складе"
        КОГДА Остатки.КоличествоОстаток = 0 ТОГДА "Закончился"
        ИНАЧЕ "В наличии"
    КОНЕЦ КАК Статус
ИЗ
    Справочник.Номенклатура КАК Товары
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
    ПО Остатки.Номенклатура = Товары.Ссылка

Обратите внимание: сначала проверяем ЕСТЬ NULL (нет строки вообще), и только потом = 0 (строка есть, но количество нулевое) — это два разных случая пустоты.

ЗначениеЗаполнено вне запроса: проверка результата

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

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    Если НЕ ЗначениеЗаполнено(Выборка.Контрагент) Тогда
        Сообщить("У заказа " + Выборка.Ссылка + " не заполнен контрагент");
    КонецЕсли;
КонецЦикла;

Это удобно для проверки «на выходе», но не заменяет отбор в запросе: если строк без значения много, отфильтровать их условием ГДЕ … ЕСТЬ NULL или = ЗНАЧЕНИЕ(…ПустаяСсылка) быстрее, чем перебирать всю выборку в цикле.

Частые ошибки при проверке на пустое значение в запросе 1С

  • Сравнение с NULL через =. Условие Поле = NULL никогда не истинно и молча не отбирает строки. Для NULL — только оператор ЕСТЬ NULL / ЕСТЬ НЕ NULL.
  • Путают NULL и пустую ссылку. После левого соединения приходит NULL, а незаполненный реквизит в основной таблице — пустая ссылка. Это разные проверки: ЕСТЬ NULL против = ЗНАЧЕНИЕ(…ПустаяСсылка).
  • Забыли обернуть поле в ЕСТЬNULL(). Любая арифметика с NULL даёт NULL — суммы и итоги «схлопываются». Все числовые поля из левого соединения оборачивайте в ЕСТЬNULL(Поле, 0).
  • Сравнение составного поля с пустой ссылкой. Для поля составного типа «ничего не выбрано» — это НЕОПРЕДЕЛЕНО, а не пустая ссылка конкретного справочника.
  • Проверка строки без СокрЛП. Строка из пробелов не равна "". Если такие значения возможны, сравнивайте СокрЛП(Поле) = "".

Частые вопросы о проверке на пустое значение в запросе 1С

Почему условие Поле = NULL не работает в запросе 1С?

Потому что NULL нельзя сравнивать через =: результат такого сравнения всегда неопределён, и строки не отбираются. Используйте оператор ЕСТЬ NULL для отбора пустых значений и ЕСТЬ НЕ NULL — для заполненных.

Чем отличается ЕСТЬ NULL от функции ЕСТЬNULL?

ЕСТЬ NULL — это оператор-проверка: он возвращает Истина/Ложь и применяется в секции ГДЕ или в ВЫБОР. ЕСТЬNULL(Поле, Замена) — это функция-замена: она возвращает второй аргумент, если первый равен NULL, и используется в списке выбираемых полей.

Как проверить пустую ссылку в запросе 1С?

Сравнением с оператором ЗНАЧЕНИЕ: Поле = ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка). Для поля составного типа «ничего не выбрано» сравнивайте с НЕОПРЕДЕЛЕНО, а не с пустой ссылкой конкретного типа.