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

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

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

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

Проверка на пустую ссылку — одна из самых частых задач при написании запросов в 1С 8. Пустая ссылка возникает, когда реквизит ссылочного типа не заполнен: документ не выбран, контрагент не указан, склад оставлен пустым. Если не отфильтровать такие записи, в отчёты попадут строки с пустыми значениями, а соединения таблиц дадут неожиданные результаты.

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

Ниже разобраны все рабочие способы с примерами кода, пояснением, когда какой вариант применять, и типичные ошибки, из-за которых проверка «молча» не срабатывает.

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

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

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

Эта разница критична на практике: если реквизит просто не заполнен пользователем, нужна проверка на пустую ссылку; если поле пришло из соединения — проверка на NULL. Смешение этих случаев — самая частая причина «неправильно работающих» отборов.

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

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

ВЫБРАТЬ

ПоступлениеТоваров.Ссылка,

ПоступлениеТоваров.Контрагент

ИЗ

Документ.ПоступлениеТоваровУслуг КАК ПоступлениеТоваров

ГДЕ

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

Такой запрос вернёт все документы, где контрагент не заполнен. Обратная проверка — на заполненность — делается оператором неравенства:

ГДЕ

ПоступлениеТоваров.Контрагент <> ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)

Ограничение способа: тип ссылки в ЗНАЧЕНИЕ() должен совпадать с типом проверяемого поля. Если реквизит составного типа (например, контрагент может быть справочником «Контрагенты» или «Организации»), проверку на пустоту одного конкретного типа недостаточно — об этом ниже.

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

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

Запрос = Новый Запрос;

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

"ВЫБРАТЬ

| Док.Ссылка

|ИЗ

| Документ.ПоступлениеТоваровУслуг КАК Док

|ГДЕ

| Док.Склад = &ПустойСклад";

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

Результат = Запрос.Выполнить();

Параметр обязан иметь тот же тип, что и поле. Если передать Неопределено или пустую ссылку другого объекта, сравнение не сработает так, как ожидается. Для составных реквизитов можно передать параметр-список из пустых ссылок всех допустимых типов и проверять условием НЕ Поле В (&СписокПустых).

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

Сравнение способов проверки

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

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

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

Гибко: тип определяется в момент выполнения, можно передать список пустых ссылок. Требует кода установки параметра.

ЕСТЬ NULL / ЕСТЬNULL()

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

Проверка на NULL при соединениях таблиц

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

ВЫБРАТЬ

Номенклатура.Ссылка,

Остатки.КоличествоОстаток

ИЗ

Справочник.Номенклатура КАК Номенклатура

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки

ПО Номенклатура.Ссылка = Остатки.Номенклатура

ГДЕ

Остатки.КоличествоОстаток ЕСТЬ NULL

Часто нужно не отфильтровать, а подставить значение по умолчанию вместо NULL — для этого служит функция ЕСТЬNULL(Поле, ЗначениеПоУмолчанию). Например, вывести ноль вместо отсутствующего остатка: ЕСТЬNULL(Остатки.КоличествоОстаток, 0).

Комбинированная проверка «поле пустое или его нет из-за соединения» записывается так:

ГДЕ

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

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

Составные типы и неопределённые реквизиты

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

Надёжный вариант — передать в параметр массив или список значений со всеми пустыми ссылками допустимых типов и проверять вхождение:

СписокПустых = Новый СписокЗначений;

СписокПустых.Добавить(Справочники.Контрагенты.ПустаяСсылка());

СписокПустых.Добавить(Справочники.Организации.ПустаяСсылка());

СписокПустых.Добавить(Неопределено);

Запрос.УстановитьПараметр("Пустые", СписокПустых);

// В тексте запроса: ГДЕ Док.Плательщик В (&Пустые)

Для реквизитов типа «Характеристика» и полей, где тип определяется другим полем, дополнительно полезна функция ТИПЗНАЧЕНИЯ() и проверка Поле ССЫЛКА Справочник.Контрагенты, чтобы отделить ссылки нужного вида от прочих значений.

Проверка результата и типичные ошибки

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

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

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

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

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

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

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

Строки нет — вероятно, проверяется NULL или неверный тип

Заполненные документы
Норма

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

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

Попадают — условие записано с ошибкой логики

Поле после левого соединения
Норма

Отсутствие пары отлавливается через ЕСТЬ NULL

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

Условие с ЗНАЧЕНИЕ() не находит такие строки

Где ещё пригодится проверка: СКД, динамические списки, виртуальные таблицы

В отчётах на СКД условие на пустую ссылку добавляется в текст запроса набора данных теми же конструкциями, а в пользовательских отборах доступен вид сравнения «Не заполнено», который компоновка преобразует самостоятельно. Если отбор задаётся программно, надёжнее явно прописать условие в запросе.

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

Итог

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

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

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

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

Нет. Пустая ссылка — это значение ссылочного типа, а не строка. Сравнение Поле = "" для ссылочного поля либо вызовет ошибку несовместимости типов, либо не даст результата. Используйте ЗНАЧЕНИЕ() с пустой ссылкой нужного объекта.

Как проверить, что ссылка заполнена (не пустая)?

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

Чем отличается проверка в запросе от проверки в коде?

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

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

Чаще всего тип в ЗНАЧЕНИЕ() не совпадает с типом реквизита (например, проверяете «Контрагенты», а поле типа «Партнеры») либо поле берётся из левого соединения и содержит NULL. Выведите поле в результат запроса и посмотрите, что в нём фактически.

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

Передайте условие прямо в параметры виртуальной таблицы, например: РегистрНакопления.Товары.Остатки(, Склад = &ПустойСклад). Это эффективнее, чем фильтровать в секции ГДЕ после получения всех данных.

Работает ли ЗНАЧЕНИЕ() для перечислений?

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