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