Работа с пустыми значениями в запросах 1С — одна из самых распространённых задач, с которыми сталкиваются разработчики при создании отчётов, обработок и интеграций. Неправильная обработка NULL может приводить к ошибкам в логике, искажению данных или даже падению производительности системы. В этой статье мы разберём не только базовый синтаксис проверки на пустоту, но и нюансы, о которых часто умалчивают в стандартной документации.
Почему эта тема актуальна? В реальных базах данных 1С:Предприятие пустые значения встречаются повсюду: незаполненные реквизиты справочников, отсутствующие ссылки на документы, пропущенные даты или числовые поля. Например, при формировании отчёта по продажам вы можете столкнуться с ситуацией, когда у некоторых товаров не указан поставщик — и если не учесть этот момент, итоговая выборка окажется некорректной. Далее мы рассмотрим, как избежать таких проблем на практике.
Что такое пустое значение в 1С и как оно хранится в базе
В 1С:Предприятие пустое значение обозначается ключевым словом NULL (в запросах) или функцией ЗначениеЗаполнено() в встроенном языке. Однако важно понимать, что NULL — это не то же самое, что пустая строка ("") или ноль (0). Это специальный маркер, указывающий на отсутствие данных в поле.
Внутренне платформа 1С хранит пустые значения по-разному в зависимости от типа данных:
- 📌 Для ссылочных типов (справочники, документы) — это отсутствие ссылки на объект.
- 📅 Для дат — это дата
'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через=. ВыражениеГДЕ Поле = NULLвсегда вернёт пустой результат, так какNULLне равно самому себе. Правильно:ГДЕ Поле ЕСТЬ NULL. - Использование
НЕсЕСТЬ NULL. КонструкцияГДЕ НЕ Поле ЕСТЬ NULLсинтаксически верна, но может сбивать с толку. Лучше использоватьГДЕ ЗНАЧЕНИЕ ЗАПОЛНЕНО(Поле). - Пустые строки vs
NULL. Если поле может содержать как пустые строки, так иNULL, проверка только наЕСТЬ NULLне покроет все случаи. Нужно использоватьГДЕ (Поле ЕСТЬ NULL ИЛИ Поле = ""). - Агрегатные функции и
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?
Вероятные причины:
- Поле на самом деле содержит не
NULL, а пустую строку или ноль. Проверьте данные напрямую. - В запросе есть дополнительные условия, которые отсеивают эти записи (например, соединение с другой таблицей, где нет соответствий).
- Если используете
РАЗЛИЧНЫЕилиГРУППИРОВКА,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 = "Значение"