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