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