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

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

Если вы когда-нибудь получали неожиданные результаты при фильтрации данных по пустым значениям или сталкивались с сообщением "Поле объекта не обнаружено" — этот материал поможет разобраться в причинах и найти правильное решение. Мы также рассмотрим, как NULL ведёт себя в разных контекстах: при работе с реквизитами объектов, в результатах запросов и при обмене данными через JSON или XML.

Для наглядности каждый метод будет проиллюстрирован практическими примерами кода, а в конце статьи вы найдёте сводную таблицу с сравнением подходов и рекомендациями по их применению.

Что такое NULL в 1С и почему его нельзя сравнить напрямую

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

Такое поведение обусловлено стандартом SQL, который лежит в основе языка запросов . В классическом SQL сравнение с NULL всегда даёт неизвестный результат (UNKNOWN), что требует использования специальных операторов. В эта логика сохранена, но дополнена собственными механизмами.

Примеры некорректных сравнений:

Если Реквизит = NULL Тогда // Всегда Ложь, даже если Реквизит пуст

Если Реквизит <> NULL Тогда // Всегда Ложь, даже если Реквизит заполнен

Чтобы корректно работать с NULL, в предусмотрены специальные функции и операторы. Их выбор зависит от контекста: работаете ли вы в модуле на встроенном языке или формируете запрос к базе данных.

📊 Как часто вы сталкиваетесь с NULL в 1С?
Ежедневно
Несколько раз в неделю
Редко
Никогда

Способы проверки на NULL в коде 1С

На уровне встроенного языка для проверки на NULL используются две основные функции: ЗначениеЗаполнено() и ЗначениеПустое(). Они являются взаимно обратными и покрывают большинство сценариев.

1. Функция ЗначениеЗаполнено() возвращает Истина, если значение не равно NULL:

Если ЗначениеЗаполнено(Реквизит) Тогда

// Реквизит содержит данные (не NULL)

КонецЕсли;

2. Функция ЗначениеПустое() возвращает Истина, если значение равно NULL:

Если ЗначениеПустое(Реквизит) Тогда

// Реквизит пуст (NULL)

КонецЕсли;

Эти функции работают с любыми типами данных: примитивами (Число, Строка), ссылками на объекты, а также с коллекциями (Массив, Структура). Например, для строки "" или массива с нулевым количеством элементов ЗначениеЗаполнено() вернёт Истина, так как это не NULL, а инициализированные объекты.

Дополнительные нюансы:

  • 🔹 ЗначениеЗаполнено() корректно обрабатывает неинициализированные переменные (в отличие от прямого сравнения).
  • 🔹 Для ссылочных типов (например, СправочникСсылка.Номенклатура) функция проверяет не только NULL, но и пустые ссылки (например, созданные через Справочники.Номенклатура.ПустаяСсылка()).
  • 🔹 В контексте управляемых форм эти функции часто используются для валидации полей перед сохранением.
💡

Для проверки "пустоты" строк или коллекций дополнительно используйте функции СтрокаПустая() или Массив.Количество() = 0 — они покрывают случаи, когда значение не NULL, но фактически не содержит данных.

Работа с NULL в запросах 1С

В языке запросов для работы с NULL предусмотрены специальные операторы: ЕСТЬ NULL и ЗНАЧЕНИЕ. Их синтаксис отличается от привычных сравнений, что часто вызывает путаницу у начинающих разработчиков.

1. Оператор ЕСТЬ NULL проверяет, что поле содержит NULL:

ВЫБРАТЬ

Наименование

ИЗ

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

ГДЕ

Артикул ЕСТЬ NULL

2. Оператор ЗНАЧЕНИЕ позволяет подставить значение по умолчанию вместо NULL:

ВЫБРАТЬ

Наименование,

ЗНАЧЕНИЕ(Артикул, "") КАК Артикул

ИЗ

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

Ключевые различия между операторами:

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

Важный момент: в запросах нельзя использовать функции ЗначениеЗаполнено() или ЗначениеПустое() — они доступны только на встроенном языке.Attempting to use them will result in a syntax error.

Для сложных условий с NULL в запросах часто применяют конструкцию ВЫРАЗИТЬ:

ВЫБРАТЬ

Наименование,

ВЫРАЗИТЬ(ЕСТЬNULL(Артикул) КАК Логическое) КАК АртикулПуст

ИЗ

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

Почему нельзя использовать = NULL в запросах?

В стандарте SQL сравнение с NULL всегда возвращает UNKNOWN (неизвестно), а не TRUE или FALSE. Поэтому конструкции вида WHERE Поле = NULL не работают — они никогда не дадут результата. Операторы ЕСТЬ NULL/НЕ ЕСТЬ NULL специально введены для обработки этой ситуации.

Типичные ошибки при сравнении с NULL

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

  1. Прямое сравнение с NULL:
    Если Реквизит = NULL Тогда // ОШИБКА! Всегда Ложь
    Правильно: Если ЗначениеПустое(Реквизит) Тогда
  2. Использование НЕ с ЗначениеЗаполнено():
    Если НЕ ЗначениеЗаполнено(Реквизит) Тогда // Корректно, но менее читаемо
    Лучше: Если ЗначениеПустое(Реквизит) Тогда
  3. Путаница между NULL и пустой строкой:
    Если Реквизит = "" Тогда // Проверяет пустую строку, а не NULL!
    Для проверки обоих случаев: Если ЗначениеПустое(Реквизит) ИЛИ Реквизит = "" Тогда

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

Ещё один подводный камень — работа с коллекциями. Если элемент массива или структуры равен NULL, стандартные методы вроде Найти() или ВГраницах() могут вести себя неинтуитивно. Например:

Массив = Новый Массив;

Массив.Добавить(Новый Структура("Поле", NULL));

Сообщить(Массив[0].Поле = NULL); // Выведет Ложь!

💡

Всегда используйте ЗначениеПустое() для проверки элементов коллекций на NULL — это гарантирует корректное поведение даже в сложных структурах данных.

NULL в обмене данными (JSON, XML, веб-сервисы)

При интеграции с внешними системами через JSON, XML или REST API обработка NULL требует особого внимания. Разные форматы по-разному представляют пустые значения, и их некорректное преобразование может привести к потерям данных.

В JSON NULL передаётся как литерал null. При чтении такого значения в оно автоматически преобразуется в NULL платформы:

Данные = JSON.Прочитать('{"field": null}');

Сообщить(ЗначениеПустое(Данные.field)); // Истина

В XML ситуация сложнее: пустые элементы могут передаваться разными способами:

  • 📌 <field/> — пустой элемент (часто интерпретируется как NULL)
  • 📌 <field></field> — элемент с пустым содержимым (может стать пустой строкой)
  • 📌 <field xsi:nil="true"/> — явное указание на NULL (требует настройки XSD-схемы)

Для корректной обработки рекомендуется:

  1. Настраивать XDTO-пакеты с явным указанием типов данных.
  2. Использовать ЗначениеПустое() для проверки прочитанных значений.
  3. При записи в JSON/XML явно указывать NULL через Неопределено:
    JSON.Записать(Неопределено); // Сериализуется в null

Явно указаны типы данных в XDTO-пакетах|Используется ЗначениеПустое() для проверки входящих значений|Тестируется обработка пустых элементов XML|Проверяется сериализация NULL в JSON-->

Оптимизация запросов с условиями на NULL

Условия с NULL в запросах могут значительно влиять на производительность, особенно при работе с большими таблицами. Вот ключевые рекомендации по оптимизации:

1. Избегайте ЗНАЧЕНИЕ в условиях ГДЕ:

Конструкции вида ГДЕ ЗНАЧЕНИЕ(Поле, 0) = 0 вынуждают СУБД выполнять функцию для каждой строки, что блокирует использование индексов. Лучше разделить условие:

ВЫБРАТЬ

Поле1

ИЗ

Таблица

ГДЕ

Поле ЕСТЬ NULL

ИЛИ Поле = 0

2. Используйте индексы по полям с частыми проверками на NULL:

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

3. Ограничивайте результаты с NULL на стороне СУБД:

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

Пример неоптимального кода:

Запрос = Новый Запрос;

Запрос.Текст = "ВЫБРАТЬ Поле1 ИЗ Таблица";

Результат = Запрос.Выполнить();

Выборка = Результат.Выбрать();

Пока Выборка.Следующий() Цикл

Если НЕ ЗначениеПустое(Выборка.Поле1) Тогда // Фильтрация в коде!

// Обработка

КонецЕсли;

КонецЦикла;

Оптимизированный вариант:

Запрос.Текст = "ВЫБРАТЬ Поле1 ИЗ Таблица ГДЕ НЕ Поле1 ЕСТЬ NULL";
💡

Фильтрация по NULL на уровне запроса может ускорить выполнение в 10-100 раз для больших таблиц за счёт использования индексов.

Практические примеры и решения типичных задач

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

Задача 1: Заполнить пустые значения в таблице значений

Допустим, у вас есть ТаблицаЗначений с колонкой Цена, в которой часть значений — NULL. Нужно заменить их на 0:

Для Каждого Строка Из Таблица Цикл

Если ЗначениеПустое(Строка.Цена) Тогда

Строка.Цена = 0;

КонецЕсли;

КонецЦикла;

Задача 2: Найти документы с незаполненными реквизитами

Через запрос:

ВЫБРАТЬ

Ссылка КАК Документ

ИЗ

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

ГДЕ

Контрагент ЕСТЬ NULL

ИЛИ ДатаДоставки ЕСТЬ NULL

Задача 3: Сериализация объекта с NULL в JSON

Чтобы пустые поля не попали в результат:

Процедура ЗаписатьЕслиНеПусто(ЗаписьJSON, ИмяПоля, Значение)

Если НЕ ЗначениеПустое(Значение) Тогда

ЗаписьJSON.ЗаписатьИмя(ИмяПоля);

ЗаписьJSON.ЗаписатьЗначение(Значение);

КонецЕсли;

КонецПроцедуры;

Задача 4: Проверка NULL в динамическом списке

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

Элементы.Отбор.Добавить("Реквизит", ТипСравнения.Равно, Неопределено);
Как проверить массив на наличие NULL?

Используйте комбинацию Массив.Найти(Неопределено) или цикл с ЗначениеПустое():

Если Массив.Найти(Неопределено) <> Неопределено Тогда

// В массиве есть NULL

КонецЕсли;

FAQ: Частые вопросы о NULL в 1С

Почему условие Если Значение = NULL Тогда не работает?

Потому что в (как и в SQL) прямое сравнение с NULL всегда возвращает Ложь. Для проверки на NULL используйте функции ЗначениеПустое() или ЗначениеЗаполнено(), а в запросах — операторы ЕСТЬ NULL/НЕ ЕСТЬ NULL.

Как отличить NULL от пустой строки?

NULL — это отсутствие значения, а пустая строка ("") — это инициализированное значение. Используйте:

Если ЗначениеПустое(Значение) Тогда

// NULL

ИначеЕсли Значение = "" Тогда

// Пустая строка

КонецЕсли;

Можно ли в 1С создать переменную со значением NULL?

Да, с помощью ключевого слова Неопределено:

Переменная = Неопределено;

Это эквивалент NULL на встроенном языке.

Как передать NULL в параметр запроса?

Используйте Неопределено:

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

В тексте запроса параметр можно сравнивать с NULL через ЕСТЬ NULL.

Почему после десериализации JSON поле стало NULL?

Это происходит, если:

  • В JSON поле было null.
  • Поле отсутствовало в JSON, а в не было значения по умолчанию.
  • Тип данных в не совпал с типом в JSON (например, число вместо строки).

Проверяйте структуру JSON и настройки XDTO.