При разработке сложных отчетов и обработок в платформе 1С:Предприятие 8 программисты часто сталкиваются с необходимостью фильтрации данных на стороне СУБД. Самый распространенный сценарий — необходимость отобрать только те записи, где конкретное поле содержит данные, или, наоборот, исключить пустые значения. Ошибки в логике проверки приводят к тому, что в выборку попадают лишние строки или, что хуже, теряются важные документы.
Основная сложность заключается в различии понятий «пустая строка» и значение NULL. В языке запросов 1С эти сущности обрабатываются по-разному, и непонимание этой разницы является источником большинства багов. Далее мы подробно разберем синтаксис операторов и нюансы их применения в реальных задачах.
Неверная интерпретация состояния поля может исказить итоговые цифры в регламентированных отчетах. Поэтому важно четко понимать, как работает механизм проверки заполненности непосредственно внутри текста запроса, до того как данные попадут в объект результата.
Фундаментальное различие NULL и пустой строки
В реляционных базах данных, на которых работает 1С:Предприятие, отсутствие значения обозначается специальным маркером NULL. Это не ноль, не пустая строка и не ложь. Это состояние «неизвестно» или «отсутствует». Когда вы проверяете поле на равенство пустой строке, вы проверяете именно строку длиной ноль символов, а не отсутствие значения как такового.
Если в базе данных в поле «Комментарий» ничего не записано, там может храниться NULL. Если пользователь сознательно стер текст и сохранил документ, там может быть пустая строка "". Оператор IS NULL видит только первое состояние. Для второго состояния он вернет ложь, даже если визуально поле кажется пустым.
⚠️ Внимание: Смешивание понятий
NULLи пустой строки приводит к логическим ошибкам. Если ваша бизнес-логика требует считать оба варианта «незаполненными», вам придется использовать составное условие в секцииГДЕ.
Рассмотрим пример, где это различие критично. Представьте справочник контрагентов, где поле «ИНН» может быть не заполнено (для физических лиц без статуса ИП) или очищено по ошибке. Фильтрация только по IS NULL пропустит ошибочно очищенные записи, что недопустимо при формировании реестров для налоговой.
Всегда уточняйте тип данных поля в метаданных. Для типов «Строка» возможна пустая строка, для типов «Число» или «Дата» пустое значение всегда равно NULL.
Оператор IS NULL для проверки отсутствия данных
Самый надежный и производительный способ проверить, заполнено ли значение в запросе 1С — использование оператора IS NULL или его отрицания IS NOT NULL. Этот оператор работает на уровне СУБД и использует индексы, если они построены для проверяемого поля, что обеспечивает высокую скорость выполнения даже на больших объемах данных.
Синтаксис предельно прост и читается как обычный английский текст. Если вам нужно найти все документы, у которых не указан номер внешнего соглашения, вы пишете условие, где поле соглашения IS NULL. Это стандарт SQL, который полностью поддерживается движком запросов 1С.
ВЫБРАТЬ
ДокументРеализация.Ссылка,
ДокументРеализация.Номер
ИЗ
Документ.РеализацияТоваровУслуг КАК ДокументРеализация
ГДЕ
ДокументРеализация.ВнешняяСделка IS NULL
Вы не можете написать ЕСТЬNULL(Поле) IS NULL, это вызовет синтаксическую ошибку. Проверка должна производиться над самим идентификатором поля таблицы.
Использование IS NULL предпочтительнее функций конвертации, так как позволяет базе данных использовать индексацию поля для ускорения выборки.
Функция ЕСТЬNULL и подмена значений
Иногда требуется не просто отфильтровать записи, а подменить отсутствующее значение на какое-либо дефолтное прямо в выборке. Для этого в языке запросов 1С существует функция ЕСТЬNULL. Она принимает два аргумента: проверяемое выражение и значение-заменитель, которое вернется, если первое выражение равно NULL.
Эта функция часто используется в списке выбираемых полей, чтобы избежать вывода пустых ячеек в отчете. Например, если цена может быть не указана, имеет смысл вывести ноль или прочерк. Однако использование этой функции в условии отбора ГДЕ требует осторожности, так как она может отключить использование индексов.
- 📊 Функция возвращает первый аргумент, если он не
NULL. - 🔄 Возвращает второй аргумент, если первый равен
NULL. - ⚡ Может замедлять запрос при использовании в условиях соединения (
ЛЕВОЕ СОЕДИНЕНИЕ).
Пример использования функции для формирования понятного отчета:
ВЫБРАТЬ
Номенклатура.Наименование,
ЕСТЬNULL(Номенклатура.Артикул, "Нет артикула") КАК Артикул
ИЗ
Справочник.Номенклатура КАК Номенклатура
При проверке заполненности через эту функцию в условии ГДЕ, вы фактически проверяете уже результат функции, а не исходное поле. Это допустимо, но менее эффективно. Например, условие ЕСТЬNULL(Поле, 0) = 0 сработает и для реального нуля, и для NULL, что может быть нужно не всегда.
Почему ЕСТЬNULL медленнее в WHERE?
Когда вы оборачиваете поле в функцию в условии отбора, оптимизатор запросов часто не может сопоставить это условие с индексом по исходному полю, что приводит к полному сканированию таблицы.
Специфика проверки строковых полей
Проверка полей типа Строка имеет свои особенности из-за возможности существования пустой строки. Как упоминалось ранее, IS NULL не увидит строку длиной в ноль символов. Поэтому для полной проверки строкового поля на «заполненность» в бизнес-смысле часто требуется комбинированное условие.
Чтобы отобрать только те записи, где строка действительно содержит текст, необходимо исключить и NULL, и пустую строку. Это делается с помощью логического оператора И. Такой подход гарантирует, что в выборку не попадут «технически пустые» значения.
| Значение в базе | Условие: IS NOT NULL | Условие: <> "" | Комбо: IS NOT NULL И <> "" |
|---|---|---|---|
| NULL | Ложь | Неизвестно (обычно исключается) | Ложь |
| "" (пустая строка) | Истина | Ложь | Ложь |
| "Текст" | Истина | Истина | Истина |
| " " (пробел) | Истина | Истина | Истина |
Обратите внимание на последнюю строку таблицы. Строка, содержащая только пробелы, формально считается заполненной. Если ваша задача требует игнорировать и такие значения, потребуется использование функции СТРОКА или trimming-функций, если они доступны в вашей версии платформы, либо дополнительная обработка в коде 1С после получения выборки.
⚠️ Внимание: В некоторых конфигурациях при вводе данных пользователем пробелы автоматически удаляются, но не стоит полагаться на это. Всегда проверяйте требования к валидации данных в вашей предметной области.
Использование временных таблиц для сложной фильтрации
В случаях, когда логика проверки заполненности становится слишком громоздкой для одного запроса, целесообразно использовать временные таблицы. Вы можете сначала отобрать данные в промежуточный результат, а затем провести необходимую фильтрацию или присоединение уже по очищенным данным.
Этот метод особенно полезен, когда нужно проверить заполненность полей в нескольких связанных таблицах одновременно. Разбивка процесса на этапы упрощает отладку и чтение кода. Кроме того, на временных таблицах можно создавать индексы, что ускорит последующие операции выборки.
Пример структуры такого подхода:
// Шаг 1: Помещаем данные во временную таблицу
ВЫБРАТЬ
Документ.Ссылка,
Документ.Контрагент
ПОМЕСТИТЬ ВТ_Данные
ИЗ
Документ.ЗаказКлиента КАК Документ
ГДЕ
Документ.Контрагент IS NOT NULL
;
// Шаг 2: Работаем с очищенными данными
ВЫБРАТЬ
ВТ_Данные.Ссылка
ИЗ
ВТ_Данные КАК ВТ_Данные
ГДЕ
ВТ_Данные.Контрагент.Владелец IS NOT NULL
Использование конструкции ПОМЕСТИТЬ.. ИЗ позволяет изолировать промежуточные результаты. Это также дает возможность применить условное форматирование или дополнительную логику на языке 1С между этапами выполнения запроса, если это необходимо в рамках одной транзакции.
☑️ Оптимизация работы со временными таблицами
Типичные ошибки и производительность запросов
Одной из самых частых ошибок является попытка сравнить поле с NULL через операторы равенства, например Поле = NULL. В стандарте SQL и в 1С такое сравнение всегда возвращает значение «Неизвестно» (в булевой логике 1С это трактуется как Ложь в условиях отбора). В результате запрос вернет пустой набор данных, даже если NULL значения в таблице есть.
Второй распространенной ошибкой является излишнее усложнение условий. Программисты иногда пишут НЕ (Поле IS NULL) вместо более читаемого и оптимизируемого Поле IS NOT NULL. Хотя результат будет одинаковым, читаемость кода страдает, а в редких случаях оптимизатор может сработать менее эффективно.
Также стоит избегать приведения типов в условии ГДЕ, если это не критично. Например, сравнение строкового поля с числом может привести к неявному преобразованию типов, что исключит использование индекса. Всегда старайтесь сравнивать данные совместимых типов.
⚠️ Внимание: Интерфейс и поведение конструктора запросов могут незначительно отличаться в разных версиях платформы 1С:Предприятие. Всегда сверяйте синтаксис с актуальной справкой по вашей версии конфигурации.
Для анализа производительности используйте встроенный инструмент «Монитор запросов» или функцию ПолучитьПланВыполненияЗапроса. Они покажут, какие именно условия стали «узким горлышком» и где проверка на NULL вызвала полное сканирование таблицы вместо поиска по индексу.
Правильное использование IS NULL и избегание функций над полями в WHERE-условиях — залог высокой производительности отчетов на больших объемах данных.
Часто задаваемые вопросы (FAQ)
В чем разница между ЕСТЬNULL и ISNULL в 1С?
В языке запросов 1С используется функция ЕСТЬNULL. Синтаксис ISNULL характерен для диалекта T-SQL (Microsoft SQL Server). В запросах 1С использование ISNULL вызовет ошибку синтаксиса, если только это не имя вашего собственного поля.
Как проверить, что числовое поле не равно нулю и не пустое?
Для числовых полей пустое значение — это всегда NULL. Понятия «пустое число» не существует. Поэтому достаточно использовать условие Поле IS NOT NULL. Если нужно исключить и ноль, добавьте условие И Поле <> 0.
Можно ли использовать оператор IS NULL в условиях соединения (JOIN)?
Да, это допустимо. Например, при ЛЕВОЕ СОЕДИНЕНИЕ вы можете в условии ПО добавить проверку И Таблица2.Поле IS NOT NULL. Это превратит соединение во внутреннее для тех строк, где поле заполнено, но оставит строки из левой таблицы, если условие не выполнится (зависит от логики).
Почему запрос с ЕСТЬNULL работает медленнее, чем с IS NULL?
Функция ЕСТЬNULL вычисляется для каждой строки результата до применения фильтра, если она стоит в условии ГДЕ. Это мешает механизмам индексации базы данных, заставляя СУБД перебирать все записи последовательно, что критично на больших таблицах.