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