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