К статье
Практический материал

Разработка и Конфигурация · 10 мин

ВЫБОР КОГДА в запросе 1С: проверка на пустую ссылку

Как в запросе 1С использовать конструкцию ВЫБОР КОГДА для проверки пустой ссылки: ЗНАЧЕНИЕ с пустой ссылкой, ЕСТЬNULL, примеры кода, ошибки и FAQ.

Конструкция ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ ... КОНЕЦ в языке запросов 1С — это аналог оператора CASE в SQL. Одна из самых частых задач, где она применяется, — проверка поля на пустую ссылку: например, вывести текст «Не указан» вместо пустого контрагента или подставить значение по умолчанию, когда реквизит не заполнен. Ошибки в такой проверке приводят к тому, что пустые значения «проскакивают» в отчёты и печатные формы.

Главная сложность в том, что пустая ссылка в 1С — это не NULL и не пустая строка. Это особое значение конкретного типа: СправочникСсылка.Контрагенты с нулевым уникальным идентификатором. Поэтому сравнение Контрагент = "" не сработает, а сравнение с NULL вообще относится к другому механизму — разорванным соединениям таблиц.

Ниже разобраны рабочие способы проверки: через ЗНАЧЕНИЕ() с пустой ссылкой, через параметр запроса, через ЕСТЬNULL для соединений, а также типичные ошибки с составными типами и отличия проверки в запросе от проверки в коде модуля.

Что такое пустая ссылка и чем она отличается от NULL

Пустая ссылка — это значение ссылочного типа, которое существует всегда, даже если реквизит не заполняли. У каждого справочника, документа, плана счетов и других ссылочных объектов есть предопределённая пустая ссылка. Она не равна NULL: NULL появляется только в результатах соединений таблиц, когда в присоединяемой таблице не нашлось подходящей строки.

Из этого следуют два разных сценария проверки. Если поле принадлежит основной таблице запроса и просто не заполнено — сравнивайте его с пустой ссылкой. Если поле пришло из левого соединения и строки не нашлось — оно будет NULL, и сравнение с пустой ссылкой вернёт ложь. Практический признак ошибки: в отчёте вместо ожидаемого «Не указан» вы видите пустую колонку.

Проверка через ЗНАЧЕНИЕ() внутри ВЫБОР КОГДА

Самый прямой способ — функция ЗНАЧЕНИЕ(), которая позволяет обратиться к предопределённому значению прямо в тексте запроса. Для пустой ссылки синтаксис такой: ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка). Точки доступа и движения с накоплением

ВЫБОР

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

ТОГДА "Контрагент не указан"

ИНАЧЕ РеализацияТоваров.Контрагент.Наименование

КОНЕЦ КАК КонтрагентПредставление

Условий КОГДА может быть несколько — например, отдельно обработать пустую ссылку и отдельно NULL:

ВЫБОР

КОГДА Товары.Номенклатура ЕСТЬ NULL

ТОГДА "Нет данных"

КОГДА Товары.Номенклатура = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)

ТОГДА "Не указана"

ИНАЧЕ Товары.Номенклатура.Наименование

КОНЕЦ

Ветки КОГДА проверяются сверху вниз, срабатывает первая истинная. Поэтому проверку на NULL ставьте раньше проверки на пустую ссылку, если обе возможны.

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

Проверка через параметр запроса

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

Запрос.УстановитьПараметр("ПустойКонтрагент", Справочники.Контрагенты.ПустаяСсылка());

Запрос.Текст =

"ВЫБРАТЬ

| ВЫБОР

| КОГДА Док.Контрагент = &ПустойКонтрагент

| ТОГДА ""Не указан""

| ИНАЧЕ Док.Контрагент.Наименование

| КОНЕЦ КАК КонтрагентТекст

|ИЗ

| Документ.РеализацияТоваровУслуг КАК Док";

Важно, чтобы тип параметра совпадал с типом проверяемого поля. Если поле имеет составной тип (например, контрагент или физическое лицо), сравнение с пустой ссылкой одного типа не поймает пустую ссылку другого типа — об этом ниже.

Пустая ссылка и ЕСТЬNULL при соединениях

При левом соединении отсутствующая строка даёт NULL во всех полях присоединённой таблицы. Частая задача — заменить и NULL, и пустую ссылку на одно понятное значение. Для этого комбинируют ЕСТЬNULL и ВЫБОР КОГДА:

ВЫБОР

КОГДА ЕСТЬNULL(Остатки.Склад, ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка))

= ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка)

ТОГДА "Склад не определён"

ИНАЧЕ Остатки.Склад.Наименование

КОНЕЦ

Функция ЕСТЬNULL(Поле, Замена) возвращает замену, если поле равно NULL. Подставляя в качестве замены пустую ссылку того же типа, вы сводите оба случая («нет строки» и «не заполнено») к одному значению, которое дальше проверяется одним сравнением. Типы аргументов ЕСТЬNULL должны быть совместимы, иначе запрос завершится ошибкой.

Составные типы и подводные камни

Если реквизит имеет составной тип — например, «СправочникСсылка.Контрагенты» или «СправочникСсылка.ФизическиеЛица» — пустое значение хранится как пустая ссылка одного из этих типов или как неопределённое значение. Сравнение только с одной пустой ссылкой даст неполную проверку.

Надёжный вариант — проверить оба типа или использовать ВЫРАЗИТЬ для приведения типа:

ВЫБОР

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

ТОГДА "Не указан"

КОГДА Док.Плательщик = ЗНАЧЕНИЕ(Справочник.ФизическиеЛица.ПустаяСсылка)

ТОГДА "Не указан"

КОГДА Док.Плательщик = НЕОПРЕДЕЛЕНО

ТОГДА "Не указан"

ИНАЧЕ Док.Плательщик.Наименование

КОНЕЦ

Ещё одна ловушка — сравнение строки с пустой ссылкой. Если поле строковое, проверять нужно на пустую строку Поле = "", а не на пустую ссылку. Смешение типов в сравнении не вызывает ошибки выполнения, но всегда даёт ложь, и ветка ТОГДА никогда не сработает.

Типичные ошибки
01
Сравнение ссылочного поля с пустой строкой "" — условие никогда не выполняется, пустые значения проходят в результат
02
Проверка поля из левого соединения только на пустую ссылку без ЕСТЬNULL — строки без пары дают NULL и попадают в ИНАЧЕ
03
Сравнение составного реквизита с пустой ссылкой одного типа — пустые ссылки других типов не отлавливаются
04
Обращение Поле.Наименование к пустой ссылке в ветке ИНАЧЕ без проверки — в результате появляются NULL вместо текста

Проверка пустой ссылки в коде модуля

Вне запроса, в коде на встроенном языке, пустая ссылка проверяется функцией ЗначениеЗаполнено() или прямым сравнением:

Если НЕ ЗначениеЗаполнено(Документ.Контрагент) Тогда

Сообщить("Контрагент не указан");

КонецЕсли;

Если Документ.Склад = Справочники.Склады.ПустаяСсылка() Тогда

// склад не выбран

КонецЕсли;

ЗначениеЗаполнено() универсальнее: она возвращает ложь и для пустых ссылок, и для NULL, и для Неопределено, и для пустых строк. Прямое сравнение с ПустаяСсылка() подходит, когда тип значения гарантирован. В СКД и динамических списках логика та же, что в запросе, — там используйте ЗНАЧЕНИЕ() и ЕСТЬNULL.

Способы проверки

ЗНАЧЕНИЕ(...ПустаяСсылка) в запросе

Прямо в тексте запроса, без параметров. Ограничение: тип должен быть известен на момент написания запроса

Параметр запроса

Гибко при динамическом построении и повторном использовании. Требует установки параметра в коде

ЗначениеЗаполнено() в коде

Универсальная проверка вне запроса: ловит пустые ссылки, NULL, Неопределено, пустые строки. Не применима внутри текста запроса

Как проверить результат и отладить запрос

После написания запроса проверьте его на данных, где заведомо есть и заполненные, и пустые значения. Удобный приём — временно вывести само проверяемое поле рядом с вычисляемой колонкой, чтобы увидеть, какие значения попадают в каждую ветку ВЫБОР.

Если в результате видны пустые ячейки там, где ожидался текст-замена, значит, условие не сработало: либо тип сравнения не совпал, либо значение оказалось NULL. Добавьте в выборку конструкцию ВЫБОР КОГДА Поле ЕСТЬ NULL ТОГДА "NULL" ... для диагностики — это быстро покажет природу «пустоты».

Контрольные точки

Как проверить результат

Колонка с ВЫБОР КОГДА на тестовых данных
Норма

Пустые ссылки заменены текстом, заполненные показывают представление

Тревожный признак

Пустые ячейки или NULL вместо текста-замены

Поля из левых соединений
Норма

ЕСТЬNULL обрабатывает и отсутствие строки, и незаполненность

Тревожный признак

Строки без пары в соединении дают NULL и попадают в ИНАЧЕ

Составные реквизиты
Норма

Проверены пустые ссылки всех возможных типов

Тревожный признак

Часть пустых значений не отлавливается

Частые вопросы

Чем отличается ЕСТЬ NULL от сравнения с пустой ссылкой?

NULL означает отсутствие значения и возникает в результате соединений таблиц, когда строка не найдена. Пустая ссылка — конкретное значение ссылочного типа, означающее «объект не выбран». Проверка Поле ЕСТЬ NULL ловит только NULL, а Поле = ЗНАЧЕНИЕ(...ПустаяСсылка) — только пустую ссылку. Часто нужны обе проверки.

Можно ли использовать ВЫБОР КОГДА в условии ГДЕ?

Можно, но обычно это избыточно: условия фильтрации проще записывать напрямую через И, ИЛИ и сравнения. ВЫБОР КОГДА в секции ГДЕ оправдан, когда условие фильтрации зависит от значения другого поля и не выражается простым сравнением.

Почему сравнение с пустой ссылкой не работает в динамическом списке?

Чаще всего потому, что поле имеет составной тип или произвольный тип, и фактическое пустое значение отличается от указанного в ЗНАЧЕНИЕ(). Проверьте тип реквизита в конфигураторе и добавьте проверки для всех возможных типов либо используйте ЕСТЬNULL с приведением через ВЫРАЗИТЬ.

Как проверить на пустую ссылку поле типа ДокументСсылка?

Аналогично справочнику: Поле = ЗНАЧЕНИЕ(Документ.ИмяДокумента.ПустаяСсылка). Если тип документа в реквизите составной (ссылка на несколько видов документов), проверяйте пустую ссылку каждого вида или используйте ЗначениеЗаполнено() в коде до передачи данных в запрос.

Что вернёт Поле.Наименование, если Поле — пустая ссылка?

Разыменование пустой ссылки через точку вернёт NULL, а не пустую строку. Поэтому в ветке ИНАЧЕ конструкции ВЫБОР КОГДА, если есть вероятность NULL, стоит обернуть обращение в ЕСТЬNULL с текстом-заменой.

Итог

Что важно запомнить

Пустая ссылка в запросе проверяется через ЗНАЧЕНИЕ(Тип.ПустаяСсылка) или параметр, а NULL из соединений — через ЕСТЬNULL. Внутри ВЫБОР КОГДА ставьте проверку на NULL первой, учитывайте составные типы реквизитов и не сравнивайте ссылки с пустой строкой. В коде модуля для той же задачи используйте ЗначениеЗаполнено().