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

Понимание разницы между Неопределено (NULL) и пустой строкой является критически важным для любого разработчика. В контексте SQL-подобного языка 1С эти понятия строго разграничены, и смешивать их нельзя. В этой статье мы детально разберем синтаксис операторов проверки, рассмотрим функции для замещения пустых значений и проанализируем, какой подход лучше использовать в различных сценариях программирования.

Основы работы с NULL в языке запросов 1С

В базе данных пустое значение и значение NULL — это разные сущности. Когда поле в таблице не заполнено пользователем или программно, система присваивает ему специальный маркер отсутствия данных. В запросах 1С это значение отображается как NULL. Попытка сравнить такое поле с любым другим значением, включая пустую строку или ноль, стандартными операторами равенства вернет ложный результат или NULL, что в условиях выборки трактуется как "не подходит".

Для явной проверки на отсутствие значения используется специальный синтаксис IS NULL или его отрицание IS NOT NULL. Это наиболее быстрый и оптимизированный способ фильтрации записей на уровне СУБД. Использование стандартного оператора = для сравнения с NULL является распространенной ошибкой новичков, которая приводит к тому, что нужные строки просто не попадают в результирующую выборку.

Рассмотрим пример корректного отбора записей, где поле "Комментарий" не заполнено. Такой подход гарантирует, что механизм индексации базы данных будет задействован максимально эффективно, если под поле создан соответствующий индекс.

ВЫБРАТЬ

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

Документ.Комментарий

ИЗ

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

ГДЕ

Документ.Комментарий ЕСТЬ NULL

Обратите внимание, что в условиях соединения таблиц (JOIN) также важно учитывать возможность пустых значений. Если вы соединяете таблицы по полям, которые могут быть NULL, стандартное внутреннее соединение (INNER JOIN) просто отбросит такие строки. Для сохранения всех записей из левой таблицы, даже если в правой нет совпадений или значения пусты, необходимо использовать LEFT JOIN.

💡

Используйте оператор "ЕСТЬ NULL" вместо сравнения с пустой строкой для полей типа Справочник.Ссылка или Число, так как они физически не могут хранить пустую строку, только NULL.

Функция ЕСТЬNULL для обработки данных в выборке

Часто требуется не просто отфильтровать пустые значения, а подменить их на какие-либо дефолтные данные прямо в момент формирования выборки. Для этих целей в языке запросов предусмотрена встроенная функция ЕСТЬNULL. Она принимает два аргумента: проверяемое выражение и значение-заменитель. Если первое выражение равно NULL, функция возвращает второй аргумент, в противном случае — значение самого выражения.

Эта функция особенно полезна при формировании печатных форм или экспортных файлов, где наличие пустых ячеек недопустимо. Например, если в документе не указан вес товара, в отчете желательно видеть "0" или прочерк, а не пустое место, которое может сдвинуть верстку. Применение ЕСТЬNULL позволяет избежать дополнительных циклов обработки результата запроса в коде 1С.

Синтаксис функции универсален и работает с любыми типами данных, включая ссылки, числа, строки и даты. Однако стоит помнить, что типы данных исходного поля и значения-заменителя должны быть совместимы или приводимы друг к другу, иначе возникнет ошибка выполнения запроса.

ВЫБРАТЬ

Товары.Наименование,

ЕСТЬNULL(Товары.Артикул, "Нет артикула") КАК Артикул

ИЗ

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

Использование данной функции влияет на план выполнения запроса, но в большинстве случаев это влияние минимально. Главное преимущество — чистота кода и перенос логики обработки исключительных ситуаций на уровень базы данных, что часто быстрее, чем обработка большого массива данных в памяти приложения.

☑️ Проверка использования ЕСТЬNULL

Выполнено: 0 / 4

Оператор ВЫБОР для сложной логики проверки

Когда простой подмены значения недостаточно и требуется реализовать ветвление логики непосредственно в тексте запроса, на помощь приходит оператор ВЫБОР. Он является аналогом конструкции if-else в императивных языках программирования. С его помощью можно проверять заполненность полей и возвращать совершенно разные значения или даже текстовые метки в зависимости от результата проверки.

Оператор ВЫБОР позволяет создавать вычисляемые поля с богатой логикой. Вы можете последовательно проверять несколько условий. Например, сначала проверить, заполнено ли основное поле, если нет — проверить резервное поле, и только если оба пусты, вывести стандартное сообщение. Это дает огромную гибкость при формировании сложных аналитических отчетов без необходимости писать громоздкий код на стороне клиента.

Важно соблюдать синтаксическую структуру: после ключевого слова ВЫБОР идут условия КОГДА, затем результаты ТОГДА, и обязательно завершающая часть ИНАЧЕ. Отсутствие блока ИНАЧЕ допустимо, но тогда для всех не подошедших условий будет возвращено NULL, что может быть неочевидно для читающего код.

ВЫБРАТЬ

Заказы.Номер,

ВЫБОР

КОГДА Заказы.Статус ЕСТЬ NULL ТОГДА "Новый"

ИНАЧЕ Заказы.Статус

КОНЕЦ КАК ТекущийСтатус

ИЗ

Документ.ЗаказКлиента КАК Заказы

Использование вложенных операторов ВЫБОР возможно, но может значительно усложнить чтение запроса. Если логика становится слишком запутанной, целесообразнее разбить задачу на два этапа: сначала получить данные, а затем обработать их во временной таблице или в цикле программы.

Оптимизация сложных ВЫБОР

Если оператор ВЫБОР используется в условии ГДЕ, убедитесь, что проверяемые поля проиндексированы, иначе база данных может выполнить полное сканирование таблицы, что замедлит работу при больших объемах данных.

Сравнение производительности методов проверки

Выбор между IS NULL, ЕСТЬNULL и ВЫБОР часто делается исходя не только из удобства написания кода, но и из требований к производительности. Оператор IS NULL в секции ГДЕ является самым быстрым, так как он нативно поддерживается движком СУБД и позволяет использовать индексы для мгновенного поиска записей без значения.

Функция ЕСТЬNULL в секции ВЫБРАТЬ также работает достаточно быстро, так как выполняется на уровне потока данных. Однако, если использовать её в условии ГДЕ (например, ГДЕ ЕСТЬNULL(Поле, 0) = 0), это может привести к тому, что оптимизатор запроса откажется от использования индекса по полю Поле, так как значение поля модифицируется функцией перед сравнением.

Оператор ВЫБОР является самым ресурсоемким из трех, особенно при большом количестве ветвлений. Его следует применять тогда, когда другие средства не позволяют выразить требуемую бизнес-логику. В высоконагруженных системах с миллионами записей каждое лишнее условие в ВЫБОР может добавлять миллисекунды к времени выполнения, что в сумме дает заметную задержку.

Метод Место использования Влияние на индексы Рекомендация
ЕСТЬ NULL Условие ГДЕ Положительное (использует индекс) Идеально для фильтрации
ЕСТЬNULL() Список полей ВЫБРАТЬ Нейтральное Для подмены значений в отчете
ВЫБОР Список полей или ГДЕ Отрицательное (часто сбрасывает индекс) Для сложной логики
= NULL Любое Ошибка логики (всегда Ложь) Запрещено к использованию
💡

Никогда не используйте функцию ЕСТЬNULL в условии ГДЕ для фильтрации, если важна скорость работы на больших базах. Замените её на явное сравнение ИЛИ оператор ЕСТЬ NULL.

Обработка пустых значений в соединении таблиц

Особое внимание следует уделить ситуации, когда проверка заполненности необходима для связки таблиц. При выполнении соединения LEFT JOIN строки из левой таблицы попадают в результат всегда, даже если в правой таблице нет соответствий. В таких случаях поля из правой таблицы будут равны NULL.

Если ваша задача — найти записи в основной таблице, для которых нет связанных записей в дополнительной (например, найти товары, у которых нет цен), то проверка поля правой таблицы на NULL после LEFT JOIN является стандартным паттерном. Это позволяет эффективно находить "сиротские" записи без использования вложенных запросов или оператора НЕ В.

Пример такого подхода демонстрирует, как отобрать контрагентов, у которых еще не заведен основной договор. Мы соединяем справочник контрагентов с документами договоров и фильтруем только те строки, где ссылка на договор пуста.

ВЫБРАТЬ

Контрагенты.Наименование

ИЗ

Справочник.Контрагенты КАК Контрагенты

ЛЕВОЕ СОЕДИНЕНИЕ Документ.ДоговорКонтрагента КАК Договоры

ПО Контрагенты.Ссылка = Договоры.Контрагент

ГДЕ

Договоры.Ссылка ЕСТЬ NULL

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

📊 Какой метод проверки вы используете чаще всего?
ЕСТЬ NULL в ГДЕ
Функция ЕСТЬNULL
Оператор ВЫБОР
Обработка в цикле 1С

Типичные ошибки и рекомендации по рефакторингу

Одной из самых коварных ошибок является попытка сравнить поле типа СправочникСсылка с пустой строкой "". Ссылка не может быть пустой строкой, она либо указывает на объект, либо равна NULL. Сравнение Поле = "" для ссылки всегда вернет ложь, и фильтр не сработает так, как задумано. Всегда используйте ЕСТЬ NULL для ссылочных типов.

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

⚠️ Внимание: При миграции баз данных или обновлении конфигурации типы полей могут изменяться. Поле, которое раньше было строкой и допускало пустое значение, может стать ссылкой. Обязательно проверяйте метаданные перед рефакторингом старых запросов.

Для повышения читаемости кода рекомендуется выносить сложные проверки ВЫБОР в отдельные вычисляемые поля с понятными именами, а не встраивать их прямо в условия фильтрации, если это возможно. Это упрощает отладку: вы можете временно вывести это поле в результат запроса и увидеть, какие именно значения попадают в ту или иную ветку логики.

Используйте консоль запросов для анализа плана выполнения. Если вы видите, что при проверке заполненности происходит полное сканирование таблицы (Table Scan), попробуйте переписать условие, вынеся функцию из-под знака сравнения или заменив её на оператор IS NULL.

Секрет быстрой отладки

Добавьте в конец запроса "УПОРЯДОЧИТЬ ПО" проверяемое поле. Это сгруппирует все NULL-значения в начале или конце результата, позволяя визуально оценить их количество и контекст возникновения.

Часто задаваемые вопросы (FAQ)

В чем разница между пустой строкой и NULL в 1С?

Пустая строка "" — это конкретное значение типа Строка, имеющее длину 0. NULL — это состояние отсутствия значения как такового. Поля типов Число, Дата, Ссылка не могут содержать пустую строку, для них существует только NULL. Сравнивать их напрямую нельзя.

Можно ли использовать функцию ЕСТЬNULL в условии ГДЕ?

Технически можно, но это плохая практика для производительности. Выражение ГДЕ ЕСТЬNULL(Поле, 0) = 0 заставляет базу данных вычислять функцию для каждой строки, что часто отключает использование индекса по полю Поле. Лучше написать ГДЕ (Поле = 0 ИЛИ Поле ЕСТЬ NULL).

Как проверить, что все поля в группе заполнены?

Вам нужно перечислить все поля в условии ГДЕ, соединяя их оператором И и проверяя каждое на ЕСТЬ NOT NULL. Например: ГДЕ Поле1 ЕСТЬ NOT NULL И Поле2 ЕСТЬ NOT NULL. Альтернативно можно проверить сумму функций ЕСТЬNULL, но это менее производительно.

Почему запрос возвращает строки с NULL, хотя я ставил фильтр?

Возможно, вы использовали оператор = вместо ЕСТЬ. Выражение Поле = NULL всегда ложно. Также проверьте, не используете ли вы функцию над полем в условии, что может блокировать индекс, или не забыли ли учесть тип соединения таблиц.

Как заменить NULL на 0 только для отчета, не меняя данные?

Используйте функцию ЕСТЬNULL(Поле, 0) в списке выбираемых полей секции ВЫБРАТЬ. Это изменит вывод в таблице результата или отчете, но не затронет физические данные в базе данных.