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

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

Выбор когда пустая ссылка в запросе 1С

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

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

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

Ниже разобраны рабочие варианты проверки пустой ссылки в запросе, типичные ошибки, способы верификации результата и ограничения каждого подхода. Примеры применимы к типовым конфигурациям и самописным решениям на встроенном языке запросов 1С.

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

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

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

Третий случай — составной тип поля. Если реквизит может хранить ссылки разных типов, «пустым» он может быть заполнен пустой ссылкой одного из допустимых типов либо значением Неопределено. Универсальной пустой ссылки для составного поля не существует, и это источник большинства ошибок.

Проверка через ЗНАЧЕНИЕ() в простом условии

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

Обратная проверка — условие «не равно»: ГДЕ Товары.Номенклатура <> ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка). Здесь кроется подводный камень: если поле может быть NULL (например, после левого соединения), строки с NULL в отбор не попадут, потому что NULL не равен ничему. Это нужно учитывать при проектировании запроса.

Тот же приём работает внутри ВЫБОР КОГДА, когда нужно не отфильтровать строки, а вывести признак или подставить значение по умолчанию:

ВЫБОР

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

ТОГДА "Склад не указан"

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

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

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

ВЫБОР КОГДА совместно с ЕСТЬ NULL

Если поле получено через левое соединение, корректная проверка строится в два этапа: сначала отсекается NULL, затем сравнивается с пустой ссылкой. Типовой шаблон выглядит так:

ВЫБОР

КОГДА Остатки.Склад ЕСТЬ NULL

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

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

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

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

КОНЕЦ

Порядок веток КОГДА имеет значение: условия проверяются сверху вниз, и первое выполнившееся определяет результат. Если поменять ветки местами и сначала проверить равенство пустой ссылке, для NULL-строк это условие даст ложь, и управление уйдёт в ИНАЧЕ — с некорректным результатом.

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

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

= ЗНАЧЕНИЕ(...ПустаяСсылка)

Подходит для полей, гарантированно не содержащих NULL. Не ловит NULL после соединений и пустые ссылки других типов в составном поле.

ЕСТЬ NULL

Единственный корректный способ отловить NULL. Не реагирует на пустые ссылки — их нужно проверять отдельно.

ЕСТЬNULL(Поле, ПустаяСсылка)

Объединяет NULL и пустую ссылку в одну проверку. Не подходит, если NULL и пустая ссылка имеют разный смысл.

Составные типы и Неопределено

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

Надёжный шаблон для составного поля — перечислить все допустимые пустые ссылки через ИЛИ, а при риске NULL добавить соответствующую ветку:

ВЫБОР

КОГДА Док.Плательщик ЕСТЬ NULL

ТОГДА ИСТИНА

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

ТОГДА ИСТИНА

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

ТОГДА ИСТИНА

ИНАЧЕ ЛОЖЬ

КОНЕЦ КАК ПлательщикНеУказан

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

Пошаговый порядок написания проверки

Чтобы не гадать, какой вариант выбрать, удобно действовать по фиксированному алгоритму: сначала определить природу поля, затем подобрать проверку и обязательно проверить результат на реальных данных.

Порядок действий
  1. 1
    Откройте метаданные реквизита и определите его тип: одиночный ссылочный или составной.
  2. 2
    Выясните, участвует ли поле в соединениях запроса — если да, возможен NULL.
  3. 3
    Для одиночного типа без NULL используйте сравнение с ЗНАЧЕНИЕ(Тип.ПустаяСсылка).
  4. 4
    При наличии соединений добавьте первой веткой КОГДА проверку ЕСТЬ NULL.
  5. 5
    Для составного типа перечислите пустые ссылки всех допустимых типов через ИЛИ.
  6. 6
    Выполните запрос в консоли запросов на тестовой базе и проверьте, что строки с известными пустыми значениями попали в нужную ветку.

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

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

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

Строка с пустой ссылкой в поле
Норма

Попадает в ветку «пусто» конструкции ВЫБОР

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

Попадает в ИНАЧЕ или пропадает из выборки

Строка с NULL после левого соединения
Норма

Обрабатывается веткой ЕСТЬ NULL

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

Попадает в ИНАЧЕ, как будто поле заполнено

Строка с заполненной ссылкой
Норма

Попадает в ИНАЧЕ с корректным значением

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

Ошибочно отмечена как пустая

Типичные ошибки и их последствия

Самая распространённая ошибка — сравнение поля составного типа только с одной пустой ссылкой. Запрос при этом выполняется, но строки, где поле заполнено пустой ссылкой другого типа, считаются «заполненными». В отчётах это проявляется как лишние строки с пустым представлением.

Вторая частая проблема — сравнение с пустой строкой вместо пустой ссылки: условие вида Док.Контрагент = "" для ссылочного поля. Для полей одиночного ссылочного типа такое сравнение может привести к ошибке исполнения или к неявному приведению типов с непредсказуемым результатом — в любом случае это недопустимый приём.

Третья ошибка — игнорирование NULL в условии «не равно». Конструкция ГДЕ НЕ Поле = ЗНАЧЕНИЕ(...ПустаяСсылка) после левого соединения отсекает все NULL-строки, хотя разработчик обычно ожидает обратного. Правильный вариант: ГДЕ ЕСТЬNULL(Поле, ЗНАЧЕНИЕ(...ПустаяСсылка)) <> ЗНАЧЕНИЕ(...ПустаяСсылка) либо явная комбинация условий через ИЛИ.

Типичные ошибки
01
Сравнение составного поля с одной пустой ссылкой — пустые ссылки других типов проходят как «заполненные».
02
Игнорирование NULL после левого соединения — строки молча выпадают из отбора или попадают не в ту ветку ВЫБОР.
03
Сравнение ссылочного поля с пустой строкой — ошибка выполнения или неявное приведение типов.
04
Неверный порядок веток КОГДА — проверка пустой ссылки стоит раньше проверки ЕСТЬ NULL, и NULL уходит в ИНАЧЕ.
05
Проверка только в конструкторе запроса без прогона на реальных данных — логическая ошибка остаётся незамеченной.

Альтернативы и границы применимости

Не всегда проверку пустоты нужно делать в запросе. Если результат запроса дальше обрабатывается кодом, иногда проще выгрузить поле как есть и проверить его методами встроенного языка: ЗначениеЗаполнено() корректно обрабатывает и пустые ссылки, и Неопределено, и NULL из выборки. Это оправдано, когда логика ветвления сложная и в запросе превращается в громоздкий ВЫБОР.

Обратная сторона — производительность и объём передаваемых данных. Если по признаку «пусто» нужно отфильтровать строки, делать это надо именно в запросе через ГДЕ: выгрузка всех строк с последующим отбором в коде заметно медленнее на больших таблицах. Правило простое: фильтрация — в запросе, сложное представление — можно в коде.

Для виртуальных таблиц регистров учитывайте, что отбор в параметрах виртуальной таблицы выполняется до соединения и работает быстрее, чем условие в ГДЕ основного запроса. Если проверка на пустую ссылку относится к измерению регистра, переносите её в параметры виртуальной таблицы — это и быстрее, и исключает появление NULL на этом этапе.

Маршрут решения

Как выбрать действие

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

FAQ

Чем NULL отличается от пустой ссылки в запросе 1С?

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

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

Потому что для строк без пары поле содержит NULL, а сравнение NULL с любым значением даёт ложь — включая отрицание через НЕ или <>. Чтобы такие строки не терялись, оберните поле в ЕСТЬNULL() с подстановкой пустой ссылки или добавьте условие ЕСТЬ NULL через ИЛИ.

Как проверить пустоту поля составного типа одним условием?

Универсального одного условия нет. Перечислите пустые ссылки всех допустимых типов через ИЛИ внутри одной ветки КОГДА и при необходимости добавьте сравнение с НЕОПРЕДЕЛЕНО. Если составное поле участвует в соединении, первой проверяйте ЕСТЬ NULL.

Можно ли сравнивать ссылочное поле с пустой строкой?

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

Что быстрее: ВЫБОР КОГДА в полях или отбор в ГДЕ?

Это разные задачи. ГДЕ отсекает строки до выборки и снижает объём обрабатываемых данных — для фильтрации всегда используйте его. ВЫБОР КОГДА в списке полей не сокращает выборку, а лишь формирует значение колонки, поэтому применяется для представления, а не для отбора.

Как проверить пустую ссылку в параметре виртуальной таблицы регистра?

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

Итог

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

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