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

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

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

Как проверить заполненность реквизита в запросе 1С: условия для строк, чисел, дат, ссылок, NULL. Примеры кода, типичные ошибки и разбор способов проверки.

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

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

Ниже разобраны все основные сценарии: проверка строк, чисел, дат, ссылок, значения NULL, а также проверка в конструкции ВЫБОР и в параметрах виртуальных таблиц. Примеры приведены для синтаксиса языка запросов, одинакового для всех современных версий платформы 1С 8.3.

Почему в запросе нет единой проверки «ЗначениеЗаполнено»

Во встроенном языке 1С есть функция ЗначениеЗаполнено(), которая универсально определяет заполненность любого значения. В языке запросов её аналога нет — это сознательное ограничение. Запрос транслируется в SQL, а на уровне СУБД каждый тип данных имеет собственное представление «пустоты», и платформа не может подставить единое условие за разработчика.

Поэтому проверка всегда строится на сравнении с конкретным «нулевым» значением типа. Дополнительная сложность — составные типы реквизитов. Если реквизит объявлен как «Строка(50) или СправочникСсылка.Контрагенты», то в незаполненном состоянии он содержит неопределённое значение, и простое сравнение с пустой строкой может не сработать корректно. Надёжнее проверять оба варианта через ИЛИ.

Проверка строковых реквизитов

Строковый реквизит считается пустым, если равен пустой строке. Простейшая проверка в секции ГДЕ:

ВЫБРАТЬ

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

Номенклатура.Артикул

ИЗ

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

ГДЕ

Номенклатура.Артикул = ""

Однако сравнение с пустой строкой имеет тонкость: для строк неограниченной длины и при некоторых настройках СУБД сравнение может вести себя неожиданно из-за пробельных символов. Более надёжный приём — проверка первого символа через функцию ПОДСТРОКА:

ГДЕ

ПОДСТРОКА(Номенклатура.Артикул, 1, 1) = ""

Такой вариант устойчив к пробелам в начале значения и корректно работает на всех поддерживаемых СУБД. Обратная проверка — «реквизит заполнен» — записывается через НЕ или обратное сравнение: ПОДСТРОКА(Реквизит, 1, 1) <> "".

Проверка чисел и дат

Числовой реквизит в незаполненном состоянии хранит ноль, поэтому проверка сводится к сравнению с нулём:

ГДЕ

Документ.СуммаОплаты = 0

Здесь важна осторожность: ноль может быть и осмысленным значением (например, бесплатная отгрузка). Если бизнес-логика различает «ноль как значение» и «не заполнено», проверка через запрос не поможет — на уровне хранения они неразличимы. В таких случаях нужен отдельный признак заполненности в данных.

Для дат пустое значение — начало времён '0001-01-01'. В запросе оно задаётся функцией ДАТАВРЕМЯ:

ГДЕ

Заказ.ДатаОтгрузки = ДАТАВРЕМЯ(1, 1, 1)

Типичная ошибка — сравнивать дату с пустой строкой или с НЕОПРЕДЕЛЕНО: такое условие либо выдаст ошибку несовместимости типов, либо молча не вернёт ни одной строки.

Проверка ссылочных реквизитов

Для ссылок пустое значение задаётся оператором ЗНАЧЕНИЕ с указанием конкретного типа и словом ПустаяСсылка:

ВЫБРАТЬ

Реализация.Ссылка

ИЗ

Документ.РеализацияТоваровУслуг КАК Реализация

ГДЕ

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

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

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

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

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

NULL появляется в результате левого или правого соединения, когда в присоединяемой таблице нет подходящей строки. Это не «пустое значение типа», а отсутствие значения как таковое, и обычные сравнения с NULL не работают: выражение Реквизит = NULL всегда ложно.

Проверка выполняется специальным оператором ЕСТЬ NULL:

ВЫБРАТЬ

Товары.Номенклатура,

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

ИЗ

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

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

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

ГДЕ

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

Такой запрос отберёт товары, по которым вообще нет записей в остатках. Если нужно заменить NULL конкретным значением для вывода, используется функция ЕСТЬNULL(Реквизит, ЗначениеПоУмолчанию).

Комбинированные проверки и вывод в ВЫБОР

На практике часто нужно не отфильтровать записи, а вывести признак заполненности — например, колонку «Договор указан: Да/Нет». Для этого используется конструкция ВЫБОР:

ВЫБРАТЬ

Реализация.Ссылка,

ВЫБОР

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

ТОГДА ""Договор не указан""

ИНАЧЕ ""ОК""

КОНЕЦ КАК СтатусДоговора

ИЗ

Документ.РеализацияТоваровУслуг КАК Реализация

Для составных реквизитов и реквизитов из соединений условия комбинируют: сначала проверяют ЕСТЬ NULL, затем сравнение с пустым значением. Порядок важен — NULL-проверка должна идти первой, иначе при отсутствии строки соединения сравнение даст неопределённый результат и запись выпадет из выборки.

Порядок действий
  1. 1
    Определите тип реквизита: строка, число, дата, ссылка или составной тип
  2. 2
    Если реквизит получен через соединение, добавьте проверку ЕСТЬ NULL
  3. 3
    Подберите пустое значение типа: "", 0, ДАТАВРЕМЯ(1,1,1) или ЗНАЧЕНИЕ(...ПустаяСсылка)
  4. 4
    Сформируйте условие в ГДЕ для отбора или в ВЫБОР для вывода признака
  5. 5
    Выполните запрос в консоли запросов на тестовых данных и сверьте количество строк с ожидаемым

Частые ошибки и как их избежать

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

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

Типичные ошибки
01
Сравнение Реквизит = NULL вместо Реквизит ЕСТЬ NULL — условие никогда не выполняется, выборка пуста
02
Сравнение даты с пустой строкой "" вместо ДАТАВРЕМЯ(1,1,1) — ошибка несовместимости типов или пустой результат
03
Проверка ссылочного реквизита сравнением с НЕОПРЕДЕЛЕНО — в запросах это работает иначе, чем во встроенном языке
04
Игнорирование NULL при левом соединении: реквизит проверяется только на пустую ссылку, а записи без соединённой строки теряются
05
Отбор по заполненности в ГДЕ после виртуальной таблицы вместо параметров — резкое падение производительности

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

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

По производительности: сравнение с константой (пустой ссылкой, нулём) использует индекс и работает быстро. Функция ПОДСТРОКА в условии отбора индекс не использует — на больших таблицах предпочтительнее прямое сравнение Реквизит = "", если оно подходит по логике.

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

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

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

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

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

Меньше — есть NULL или неучтённые значения

Выполнение запроса
Норма

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

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

Ошибка несовместимости типов при сравнении

Скорость на большой таблице
Норма

Отбор выполняется за приемлемое время

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

Долгое выполнение — условие не использует индекс

Итог

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

Единой функции проверки заполненности в языке запросов нет: строки сравнивают с "" или через ПОДСТРОКА, числа — с 0, даты — с ДАТАВРЕМЯ(1,1,1), ссылки — с ЗНАЧЕНИЕ(...ПустаяСсылка). При соединениях таблиц обязательно проверяйте ЕСТЬ NULL, а результат проверяйте парой взаимодополняющих запросов.

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

Можно ли использовать ЗначениеЗаполнено() прямо в тексте запроса?

Нет, эта функция существует только во встроенном языке. В запросе её роль выполняют сравнения с пустыми значениями конкретных типов. Если проверка сложная, можно сначала получить выборку запросом, а затем в цикле обработки результата применять ЗначениеЗаполнено() к отдельным полям.

Как проверить на заполненность реквизит составного типа?

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

Почему условие «Реквизит = NULL» не возвращает строки?

По стандарту SQL любое сравнение с NULL даёт неопределённый результат, а не ИСТИНУ. Для проверки на NULL существует специальный оператор: Реквизит ЕСТЬ NULL (или НЕ Реквизит ЕСТЬ NULL для обратной проверки).

Как вывести в отчёте «Не указано» вместо пустого реквизита?

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

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

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

Как проверить заполненность реквизита табличной части?

Обратитесь к табличной части как к отдельной таблице: Документ.РеализацияТоваровУслуг.Товары, и в секции ГДЕ примените то же сравнение по типу реквизита. Учтите, что условие по табличной части размножает строки результата — для отбора самих документов часто удобнее использовать В ИЕРАРХИИ или вложенный запрос с группировкой по ссылке.