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

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

Что такое пустое значение в 1С и как оно хранится в базе

В 1С:Предприятие пустое значение обозначается ключевым словом NULL (в запросах) или функцией ЗначениеЗаполнено() в встроенном языке. Однако важно понимать, что NULL — это не то же самое, что пустая строка ("") или ноль (0). Это специальный маркер, указывающий на отсутствие данных в поле.

Внутренне платформа хранит пустые значения по-разному в зависимости от типа данных:

  • 📌 Для ссылочных типов (справочники, документы) — это отсутствие ссылки на объект.
  • 📅 Для дат — это дата '00010101' (1 января 1 года), но в запросах она отображается как NULL.
  • 🔢 Для чисел — это не ноль, а именно отсутствие значения.
  • 📝 Для строк — это не пустая строка, а NULL (хотя при выводе в отчёт может преобразовываться в "").

Важно: в SQL-запросах (если вы работаете напрямую с базой через ADODB или Native DB) пустые значения также представлены как NULL, но их обработка может отличаться от встроенного языка 1С. Например, в SQL выражение WHERE Поле = NULL не сработает — нужно использовать WHERE Поле IS NULL.

💡

Если вы пишете запрос с параметрами и передаёте в него пустое значение из 1С, убедитесь, что параметр действительно имеет тип NULL, а не пустую строку. Для этого используйте функцию ЗначениеЗаполнено() перед передачей.

Базовый синтаксис проверки на пустое значение в запросах

Самый простой способ проверить поле на пустоту в запросе — использовать конструкцию ЕСТЬ NULL или ЗНАЧЕНИЕ ЗАПОЛНЕНО. Рассмотрим оба варианта на примерах.

Пример 1: Проверка с помощью ЕСТЬ NULL (аналог SQL-синтаксиса):

ВЫБРАТЬ

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

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

ИЗ

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

ГДЕ

Номенклатура.Поставщик ЕСТЬ NULL

Этот запрос вернёт все позиции номенклатуры, у которых не указан поставщик. Обратите внимание, что ЕСТЬ NULL работает только в условиях (ГДЕ, И, ИЛИ), но не в вычисляемых полях.

Пример 2: Проверка с помощью ЗНАЧЕНИЕ ЗАПОЛНЕНО (специфичный для 1С синтаксис):

ВЫБРАТЬ

Документ.ЗаказПокупателя.Номер,

ЕСТЬNULL(Документ.ЗаказПокупателя.ДатаОтгрузки, ДАТАВРЕМЯ(1, 1, 1)) КАК ДатаОтгрузки

ИЗ

Документ.ЗаказПокупателя КАК Документ.ЗаказПокупателя

ГДЕ

ЗНАЧЕНИЕ ЗАПОЛНЕНО(Документ.ЗаказПокупателя.Контрагент)

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

📊 Какой синтаксис проверки на пустоту вы используете чаще?
ЕСТЬ NULL
ЗНАЧЕНИЕ ЗАПОЛНЕНО
Оба варианта
Не знаю

Типичные ошибки при работе с пустыми значениями

Даже опытные разработчики иногда допускают ошибки при обработке NULL в запросах. Вот наиболее распространённые из них:

  1. Сравнение с NULL через =. Выражение ГДЕ Поле = NULL всегда вернёт пустой результат, так как NULL не равно самому себе. Правильно: ГДЕ Поле ЕСТЬ NULL.
  2. Использование НЕ с ЕСТЬ NULL. Конструкция ГДЕ НЕ Поле ЕСТЬ NULL синтаксически верна, но может сбивать с толку. Лучше использовать ГДЕ ЗНАЧЕНИЕ ЗАПОЛНЕНО(Поле).
  3. Пустые строки vs NULL. Если поле может содержать как пустые строки, так и NULL, проверка только на ЕСТЬ NULL не покроет все случаи. Нужно использовать ГДЕ (Поле ЕСТЬ NULL ИЛИ Поле = "").
  4. Агрегатные функции и NULL. Функции вроде СУММА() или СРЕДНЕЕ() игнорируют пустые значения, что может искажать результаты. Например, СУММА(ЕСТЬNULL(Поле, 0)) вернёт корректный результат.

Критическая ошибка: если в запросе используется соединение таблиц (ЛЕВОЕ СОЕДИНЕНИЕ), поля из правой таблицы, для которых не нашлось соответствий, будут содержать NULL. Это часто приводит к неожиданным результатам, если не учесть этот момент в условиях фильтрации.

Пример ошибки с соединением таблиц

Рассмотрим запрос:

ВЫБРАТЬ

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

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

ИЗ

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

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Клиенты

ПО Заказы.Контрагент = Клиенты.Ссылка

ГДЕ

Клиенты.Наименование ПОДОБНО "ООО%"

Этот запрос не вернёт заказы, у которых не указан контрагент (даже если они соответствуют другим условиям), потому что поле Клиенты.Наименование будет NULL и не пройдёт проверку ПОДОБНО.

Продвинутые техники: работа с пустыми значениями в вычисляемых полях

Часто требуется не только отфильтровать пустые значения, но и заменить их на какие-то значения по умолчанию прямо в запросе. Для этого в 1С предусмотрены функции ЕСТЬNULL и ВЫБОР.

Пример 1: Замена NULL на строку по умолчанию:

ВЫБРАТЬ

ЕСТЬNULL(Контрагенты.ИНН, "[ИНН не указан]") КАК ИНН,

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

ИЗ

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

Пример 2: Условная логика с ВЫБОР:

ВЫБРАТЬ

ВЫБОР

КОГДА Номенклатура.Вес ЕСТЬ NULL

ТОГДА 0

КОГДА Номенклатура.Вес = 0

ТОГДА 0.001

ИНАЧЕ Номенклатура.Вес

КОНЕЦ КАК ВесКорректированный,

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

ИЗ

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

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

ВЫБРАТЬ

СУММА(ЕСТЬNULL(Документ.СуммаДокумента, 0)) КАК ОбщаяСумма

ИЗ

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

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

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

2. Проверить, не искажают ли NULL результаты агрегатных функций (СУММА, СРЕДНЕЕ, МАКСИМУМ)

3. Заменить NULL на значения по умолчанию в вычисляемых полях (ЕСТЬNULL)

4. Учесть NULL при соединении таблиц (ЛЕВОЕ СОЕДИНЕНИЕ)

-->

Оптимизация производительности при работе с пустыми значениями

Проверка на NULL может влиять на скорость выполнения запросов, особенно в больших базах данных. Вот несколько советов по оптимизации:

  • 🚀 Индексы. Если поле часто проверяется на пустоту, убедитесь, что на нём есть индекс. Например, для поля Поставщик в справочнике Номенклатура индекс ускорит фильтрацию по ЕСТЬ NULL.
  • 🔍 Избегайте НЕ ЕСТЬ NULL. Конструкция ГДЕ НЕ Поле ЕСТЬ NULL может быть менее эффективна, чем ГДЕ ЗНАЧЕНИЕ ЗАПОЛНЕНО(Поле), так как последняя лучше оптимизируется платформой.
  • 📊 Ограничивайте выборку. Если вам нужны только непустые значения, добавьте условие ГДЕ ЗНАЧЕНИЕ ЗАПОЛНЕНО(Поле) как можно раньше в запрос, чтобы сократить объём обрабатываемых данных.
  • 🔄 Используйте временные таблицы. Для сложных отчётов с множеством проверок на пустоту имеет смысл сначала выбрать данные во временную таблицу, а затем обрабатывать их.

Пример оптимизированного запроса с использованием временной таблицы:

// Сначала выбираем только нужные записи

ВЫБРАТЬ РАЗРЕШЕННЫЕ

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

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

Номенклатура.Поставщик

ПОМЕСТИТЬ ВТНоменклатура

ИЗ

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

ГДЕ

ЗНАЧЕНИЕ ЗАПОЛНЕНО(Номенклатура.Поставщик)

// Затем работаем с временной таблицей

ВЫБРАТЬ

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

ВТНоменклатура.Поставщик.Наименование КАК Поставщик

ИЗ

ВТНоменклатура КАК ВТНоменклатура

💡

Использование временных таблиц особенно эффективно, если в исходном запросе много соединений или агрегатных функций. Это позволяет сократить объём данных, обрабатываемых на каждом этапе.

Практические примеры: обработка пустых значений в реальных задачах

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

Задача 1: Отчёт по продажам с учётом незаполненных реквизитов.

Допустим, нужно сформировать отчёт по продажам, где для некоторых товаров не указаны категория или поставщик. Если просто проигнорировать пустые значения, отчёт будет неполным. Решение:

ВЫБРАТЬ

ЕСТЬNULL(Номенклатура.Категория.Наименование, "[Без категории]") КАК Категория,

ЕСТЬNULL(Номенклатура.Поставщик.Наименование, "[Поставщик не указан]") КАК Поставщик,

СУММА(Документ.Количество) КАК Количество

ИЗ

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

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура

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

СГРУППИРОВАТЬ ПО

ЕСТЬNULL(Номенклатура.Категория.Наименование, "[Без категории]"),

ЕСТЬNULL(Номенклатура.Поставщик.Наименование, "[Поставщик не указан]")

Задача 2: Поиск "брошенных" документов (без ссылки на контрагента).

Иногда в базе накапливаются документы, у которых не заполнены обязательные реквизиты (например, контрагент в заказе). Чтобы их найти:

ВЫБРАТЬ

Заказы.Ссылка КАК Ссылка,

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

Заказы.Дата

ИЗ

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

ГДЕ

Заказы.Контрагент ЕСТЬ NULL

И Заказы.Дата > НАЧАЛОПЕРИОДА(МЕСЯЦ, ТЕКУЩАЯДАТА() - 365)

Задача 3: Корректировка дат с учётом пустых значений.

Если в документах есть пустые даты (например, дата отгрузки не указана), но нужно рассчитать просрочку:

ВЫБРАТЬ

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

ВЫБОР

КОГДА Заказы.ДатаОтгрузки ЕСТЬ NULL

ТОГДА ТЕКУЩАЯДАТА() - Заказы.Дата

ИНАЧЕ ТЕКУЩАЯДАТА() - Заказы.ДатаОтгрузки

КОНЕЦ КАК ПросрочкаДней

ИЗ

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

ГДЕ

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

Особенности работы с пустыми значениями в разных версиях 1С

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

Версия платформы Особенности работы с NULL Примечания
8.2 Функция ЗНАЧЕНИЕ ЗАПОЛНЕНО работает только в условиях (ГДЕ). В вычисляемых полях приходилось использовать ВЫБОР КОГДА ... ЕСТЬ NULL.
8.3.6+ Добавлена поддержка ЗНАЧЕНИЕ ЗАПОЛНЕНО в вычисляемых полях. Теперь можно писать ЕСТЬNULL(Поле, 0) или ЗНАЧЕНИЕ ЗАПОЛНЕНО(Поле) прямо в ВЫБРАТЬ.
8.3.10+ Улучшена оптимизация запросов с ЕСТЬ NULL при использовании индексов. Запросы с фильтрацией по NULL стали выполняться быстрее.
8.3.18+ Появилась возможность использования NULL в параметрах запросов без явного приведения типов. Раньше приходилось писать ЗначениеЗаполнено(Параметр) перед передачей в запрос.

⚠️ Внимание: Если вы работаете с управляемыми формами и динамическими списками, учитывайте, что фильтрация по пустым значениям в интерфейсе может вести себя иначе, чем в прямом запросе. Например, если в динамическом списке установлен фильтр "Поставщик = ПустаяСсылка", это не всегда эквивалентно ЕСТЬ NULL в запросе.

Также стоит помнить, что в тонком клиенте или веб-клиенте некоторые функции работы с пустыми значениями могут быть ограничены из-за особенностей передачи данных между сервером и клиентом. Например, если вы передаёте NULL как параметр в запрос из клиентского кода, убедитесь, что он корректно сериализуется.

FAQ: Частые вопросы по работе с пустыми значениями в 1С

Как отличить пустую строку от NULL в запросе?

Пустая строка ("") и NULL — это разные вещи. Чтобы проверить оба варианта, используйте:

ГДЕ (Поле ЕСТЬ NULL ИЛИ Поле = "")

Если нужно заменить и то, и другое на значение по умолчанию:

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

Вероятные причины:

  1. Поле на самом деле содержит не NULL, а пустую строку или ноль. Проверьте данные напрямую.
  2. В запросе есть дополнительные условия, которые отсеивают эти записи (например, соединение с другой таблицей, где нет соответствий).
  3. Если используете РАЗЛИЧНЫЕ или ГРУППИРОВКА, NULL может группироваться отдельно.

Для диагностики временно упростите запрос, оставив только проверку на NULL.

Как передать NULL в запрос как параметр из встроенного языка?

Чтобы передать NULL как параметр, используйте:

Запрос.УстановитьПараметр("Параметр", Неопределено);

или (в новых версиях):

Запрос.УстановитьПараметр("Параметр", NULL);

В тексте запроса параметр будет подставлен как NULL:

ГДЕ Поле = &Параметр

Но помните, что сравнение с NULL через = не сработает — нужно использовать ЕСТЬ NULL:

ГДЕ Поле ЕСТЬNULL &Параметр
Можно ли использовать NULL в агрегатных функциях?

Да, но нужно учитывать, что:

  • СУММА(), СРЕДНЕЕ(), МАКСИМУМ() игнорируют NULL.
  • МИНИМУМ() вернёт NULL, если все значения в группе — NULL.
  • КОЛИЧЕСТВО() считает все строки, включая те, где поле — NULL.
  • КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле) не учитывает NULL как отдельное значение.

Пример: если нужно посчитать количество записей, где поле не пустое:

ВЫБРАТЬ

КОЛИЧЕСТВО(ВЫБОР КОГДА Поле ЕСТЬ NULL ТОГДА ЛОЖЬ ИНАЧЕ ИСТИНА КОНЕЦ) КАК КоличествоНеПустых

Как обработать NULL в соединениях таблиц?

При использовании ЛЕВОЕ СОЕДИНЕНИЕ или ПОЛНОЕ СОЕДИНЕНИЕ поля из правой таблицы, для которых не нашлось соответствий, будут содержать NULL. Это может привести к неожиданным результатам, если не учесть в условиях. Например:

// Некорректно: вернёт только записи, где есть соответствие в правой таблице

ВЫБРАТЬ

ЛеваяТаблица.Поле1,

ПраваяТаблица.Поле2

ИЗ

ЛеваяТаблица КАК ЛеваяТаблица

ЛЕВОЕ СОЕДИНЕНИЕ ПраваяТаблица КАК ПраваяТаблица

ПО ЛеваяТаблица.Ключ = ПраваяТаблица.Ключ

ГДЕ

ПраваяТаблица.Поле2 = "Значение" // Это условие отсечет записи, где ПраваяТаблица.Поле2 = NULL

// Корректно: перенести условие в ON или использовать ЕСТЬNULL

ВЫБРАТЬ

ЛеваяТаблица.Поле1,

ЕСТЬNULL(ПраваяТаблица.Поле2, "[Нет данных]") КАК Поле2

ИЗ

ЛеваяТаблица КАК ЛеваяТаблица

ЛЕВОЕ СОЕДИНЕНИЕ ПраваяТаблица КАК ПраваяТаблица

ПО ЛеваяТаблица.Ключ = ПраваяТаблица.Ключ

И ПраваяТаблица.Поле2 = "Значение"