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

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

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

Как указать пустую ссылку в запросе 1С: оператор ЗНАЧЕНИЕ, параметры, проверка ЕСТЬ NULL, сравнение в СКД и типичные ошибки разработчика.

Пустая ссылка — это значение ссылочного типа, которое не указывает ни на один объект базы данных. В запросах 1С она встречается постоянно: незаполненный реквизит документа, отсутствующий контрагент в движении регистра, фильтр «показать строки без ответственного». Чтобы сравнить поле с пустой ссылкой, недостаточно написать = "" или = Неопределено — нужны специальные конструкции языка запросов.

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

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

Оператор ЗНАЧЕНИЕ — основной способ указать пустую ссылку

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

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

Такая конструкция вернёт все реализации, у которых реквизит «Контрагент» не заполнен. Полный синтаксис имени зависит от вида объекта:

  • ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка) — справочник;
  • ЗНАЧЕНИЕ(Документ.ЗаказПокупателя.ПустаяСсылка) — документ;
  • ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.ПустаяСсылка) — перечисление;
  • ЗНАЧЕНИЕ(ПланВидовХарактеристик.ДополнительныеРеквизиты.ПустаяСсылка) — план видов характеристик;
  • ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.ПустаяСсылка) — план счетов.

Ограничение способа очевидно: тип ссылки жёстко зашит в текст запроса. Если реквизит составного типа (например, «Контрагент» может быть справочником «Контрагенты» или «Организации»), сравнение с пустой ссылкой одного типа не покроет все случаи — об этом ниже.

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

Когда тип ссылки определяется в коде динамически, удобнее передать пустую ссылку параметром. Значение формируется встроенным языком, а запрос остаётся универсальным:

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

Этот пример выбирает элементы справочника, находящиеся в корне иерархии, — у них родитель не заполнен. Метод ПустаяСсылка() есть у всех менеджеров ссылочных объектов: Справочники, Документы, Перечисления, ПланыВидовХарактеристик, ПланыСчетов, ПланыОбмена, БизнесПроцессы, Задачи.

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

Пустая ссылка и NULL: в чём разница

Частая причина «неправильно работающего» запроса — смешение пустой ссылки и NULL. Это принципиально разные значения. Пустая ссылка хранится в поле таблицы, когда реквизит объекта не заполнен. NULL появляется в результате запроса, когда левое соединение не нашло пару в правой таблице, — физически в базе этого значения нет.

Соответственно и проверки разные. Поле, заполненное в объекте, сравнивают с пустой ссылкой. Поле, которое могло «не джойниться», проверяют через ЕСТЬ NULL:

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

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

Пустая ссылка или NULL

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

Для реквизитов объектов и полей таблиц, где значение физически хранится, но не заполнено

ЕСТЬ NULL / НЕ ЕСТЬ NULL

Для полей из левого соединения, виртуальных таблиц и вложенных запросов, где значение может отсутствовать

ЕСТЬNULL(Поле, ЗНАЧЕНИЕ(...ПустаяСсылка))

Когда поле может быть и NULL, и пустой ссылкой — приведение к одному виду перед сравнением

Составные типы: почему одного сравнения недостаточно

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

Надёжные варианты для составных полей:

  • перечислить все типы через ИЛИ: Поле = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка) ИЛИ Поле = ЗНАЧЕНИЕ(Справочник.Договоры.ПустаяСсылка);
  • передать параметром именно то пустое значение, которое нужно отфильтровать;
  • для проверки «заполнено ли вообще» использовать ВЫРАЗИТЬ(Поле КАК Справочник.Контрагенты) и сравнение с пустой ссылкой приведённого типа.

На практике чаще всего составное поле требуется проверить на заполненность в целом. Тогда проще сравнить строковое представление или использовать функцию Представление() в отчётах, но в отборе запроса корректнее перечисление типов — оно работает быстрее и не зависит от локализации.

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

Пустая ссылка в СКД и динамических списках

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

В динамических списках с произвольным запросом отбор «равно пустой ссылке» лучше оформлять через параметр, а не через ЗНАЧЕНИЕ(): так проще управлять условием из кода формы. Если отбор должен включаться и выключаться, параметр комбинируют с признаком использования:

bsl
ГДЕ
	(&БезОтбора
		ИЛИ Док.Ответственный = &Ответственный)

Здесь при &БезОтбора = Истина условие отключается, а при Ложь фильтрует по переданной ссылке, в том числе пустой. Это стандартный приём для управляемых форм с настраиваемыми отборами.

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

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

Порядок проверки
  1. 1
    Откройте консоль запросов (в типовых конфигурациях — внешняя обработка или встроенный инструмент разработчика) и выполните запрос с условием
  2. 2
    Убедитесь, что в результат попали записи, где реквизит визуально пуст — откройте один из объектов и проверьте поле
  3. 3
    Временно замените условие на обратное (НЕ равно пустой ссылке) и сравните количество строк: сумма двух выборок должна давать общее число записей
  4. 4
    Если условие по полю из соединения — проверьте, не нужен ли ЕСТЬ NULL вместо сравнения с пустой ссылкой
  5. 5
    Для составного поля выведите ТипЗначения(Поле) в выборку и посмотрите, какие типы реально встречаются

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

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

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

Записи с незаполненным реквизитом в выборке
Норма

Строки присутствуют, поле в объекте визуально пустое

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

Строк нет — вероятно, неверный тип в ЗНАЧЕНИЕ() или нужен ЕСТЬ NULL

Сумма выборок «равно» и «не равно» пустой ссылке
Норма

Равна общему числу записей таблицы

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

Меньше — значения других типов или NULL не учтены

Значение параметра в отладчике
Норма

Пустая ссылка конкретного типа

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

Неопределено или ссылка другого вида объекта

Граничные случаи: перечисления, строки и даты

Не всякое «пустое» значение — пустая ссылка. У примитивных типов свои значения по умолчанию, и смешивать их нельзя:

  • строка не заполнена — сравнение с "" (пустая строка, в запросе: = "");
  • число не заполнено — по сути это 0, отдельного «пустого» числа нет;
  • дата не заполнена — сравнение с ДАТАВРЕМЯ(1, 1, 1);
  • булево — только Истина или Ложь, пустого значения нет;
  • перечисление не заполнено — ЗНАЧЕНИЕ(Перечисление.Имя.ПустаяСсылка), как у ссылочных типов.

Отдельный случай — реквизиты типа «Характеристика» в механизме свойств и поля хранения значений произвольного типа. Там пустое значение может быть пустой ссылкой любого из допустимых типов, поэтому надёжнее фильтровать через параметр, передавая заготовленное значение из кода.

Если условие по пустой ссылке используется в большом регистре, следите за индексированием поля: отбор по неиндексированному измерению на миллионах записей заметно замедлит выполнение. Для часто используемых отборов имеет смысл добавить поле в индекс регистра.
ПЗ
Практическое замечание
Маршрут решения

Как выбрать способ

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

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

Чем пустая ссылка отличается от Неопределено?

Неопределено — значение встроенного языка, означающее отсутствие значения вообще, без типа. Пустая ссылка — значение конкретного ссылочного типа, которое хранится в базе и означает «объект не выбран». В запросе они не равны друг другу, и передача Неопределено в параметр вместо пустой ссылки приведёт к тому, что условие никогда не выполнится.

Почему условие «= ЗНАЧЕНИЕ(...)» не находит записи, хотя поле пустое?

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

Как проверить поле на «битую» ссылку?

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

Можно ли указать пустую ссылку в отборе СКД без программирования?

Да. В настройках отчёта добавьте отбор по нужному полю с видом сравнения «Равно» и оставьте значение незаполненным — компоновщик подставит пустую ссылку соответствующего типа. Для составных полей может потребоваться явно выбрать тип значения в диалоге выбора.

Работает ли ЗНАЧЕНИЕ() в запросах к внешним источникам данных?

Нет, оператор ЗНАЧЕНИЕ применим только к объектам метаданных конфигурации. Для внешних источников пустые значения передаются параметрами, а логика сравнения зависит от конкретного источника — например, в SQL-таблицах незаполненные ссылочные поля обычно содержат NULL или GUID нулевого значения.

Как найти элементы справочника в корне иерархии?

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

Итог

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

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