Работа с пустыми значениями (NULL) в 1С:Предприятие — одна из самых распространённых задач, с которыми сталкиваются разработчики. Несмотря на кажущуюся простоту, сравнение с NULL таит множество нюансов: от синтаксических особенностей до влияния на производительность запросов. Неправильное обращение с NULL может привести к логическим ошибкам, некорректной выборке данных или даже падению системы в критичных сценариях.
В этой статье мы разберём все доступные способы проверки на NULL в 1С 8.3 и более ранних версиях, включая операторы языка, функции платформы и особенности работы с запросами. Особое внимание уделим типичным ошибкам, которые допускают даже опытные программисты, а также оптимизации кода для работы с большими объёмами данных.
Если вы когда-нибудь получали неожиданные результаты при фильтрации данных по пустым значениям или сталкивались с сообщением "Поле объекта не обнаружено" — этот материал поможет разобраться в причинах и найти правильное решение. Мы также рассмотрим, как NULL ведёт себя в разных контекстах: при работе с реквизитами объектов, в результатах запросов и при обмене данными через JSON или XML.
Для наглядности каждый метод будет проиллюстрирован практическими примерами кода, а в конце статьи вы найдёте сводную таблицу с сравнением подходов и рекомендациями по их применению.
Что такое NULL в 1С и почему его нельзя сравнить напрямую
В 1С:Предприятие NULL — это специальное значение, обозначающее отсутствие данных. Оно принципиально отличается от пустой строки (""), числа 0 или булевого Ложь. Главная особенность NULL заключается в том, что оно не участвует в стандартных операциях сравнения — любое выражение вида Значение = NULL или Значение <> NULL всегда вернёт Ложь, даже если само Значение действительно равно NULL.
Такое поведение обусловлено стандартом SQL, который лежит в основе языка запросов 1С. В классическом SQL сравнение с NULL всегда даёт неизвестный результат (UNKNOWN), что требует использования специальных операторов. В 1С эта логика сохранена, но дополнена собственными механизмами.
Примеры некорректных сравнений:
Если Реквизит = NULL Тогда // Всегда Ложь, даже если Реквизит пуст
Если Реквизит <> NULL Тогда // Всегда Ложь, даже если Реквизит заполнен
Чтобы корректно работать с NULL, в 1С предусмотрены специальные функции и операторы. Их выбор зависит от контекста: работаете ли вы в модуле на встроенном языке или формируете запрос к базе данных.
Способы проверки на NULL в коде 1С
На уровне встроенного языка 1С для проверки на NULL используются две основные функции: ЗначениеЗаполнено() и ЗначениеПустое(). Они являются взаимно обратными и покрывают большинство сценариев.
1. Функция ЗначениеЗаполнено() возвращает Истина, если значение не равно NULL:
Если ЗначениеЗаполнено(Реквизит) Тогда
// Реквизит содержит данные (не NULL)
КонецЕсли;
2. Функция ЗначениеПустое() возвращает Истина, если значение равно NULL:
Если ЗначениеПустое(Реквизит) Тогда
// Реквизит пуст (NULL)
КонецЕсли;
Эти функции работают с любыми типами данных: примитивами (Число, Строка), ссылками на объекты, а также с коллекциями (Массив, Структура). Например, для строки "" или массива с нулевым количеством элементов ЗначениеЗаполнено() вернёт Истина, так как это не NULL, а инициализированные объекты.
Дополнительные нюансы:
- 🔹
ЗначениеЗаполнено()корректно обрабатывает неинициализированные переменные (в отличие от прямого сравнения). - 🔹 Для ссылочных типов (например,
СправочникСсылка.Номенклатура) функция проверяет не толькоNULL, но и пустые ссылки (например, созданные черезСправочники.Номенклатура.ПустаяСсылка()). - 🔹 В контексте управляемых форм эти функции часто используются для валидации полей перед сохранением.
Для проверки "пустоты" строк или коллекций дополнительно используйте функции СтрокаПустая() или Массив.Количество() = 0 — они покрывают случаи, когда значение не NULL, но фактически не содержит данных.
Работа с NULL в запросах 1С
В языке запросов 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. Вот наиболее распространённые из них:
- Прямое сравнение с
NULL:
Правильно:Если Реквизит = NULL Тогда // ОШИБКА! Всегда ЛожьЕсли ЗначениеПустое(Реквизит) Тогда - Использование
НЕсЗначениеЗаполнено():
Лучше:Если НЕ ЗначениеЗаполнено(Реквизит) Тогда // Корректно, но менее читаемоЕсли ЗначениеПустое(Реквизит) Тогда - Путаница между
NULLи пустой строкой:
Для проверки обоих случаев:Если Реквизит = "" Тогда // Проверяет пустую строку, а не NULL!Если ЗначениеПустое(Реквизит) ИЛИ Реквизит = "" Тогда
Другая распространённая проблема — неявные преобразования типов. Например, если сравнивать NULL с числом, 1С может автоматически преобразовать NULL в 0, что приведёт к неожиданным результатам. Чтобы избежать этого, всегда явно проверяйте на NULL с помощью специализированных функций.
Ещё один подводный камень — работа с коллекциями. Если элемент массива или структуры равен NULL, стандартные методы вроде Найти() или ВГраницах() могут вести себя неинтуитивно. Например:
Массив = Новый Массив;
Массив.Добавить(Новый Структура("Поле", NULL));
Сообщить(Массив[0].Поле = NULL); // Выведет Ложь!
Всегда используйте ЗначениеПустое() для проверки элементов коллекций на NULL — это гарантирует корректное поведение даже в сложных структурах данных.
NULL в обмене данными (JSON, XML, веб-сервисы)
При интеграции 1С с внешними системами через JSON, XML или REST API обработка NULL требует особого внимания. Разные форматы по-разному представляют пустые значения, и их некорректное преобразование может привести к потерям данных.
В JSON NULL передаётся как литерал null. При чтении такого значения в 1С оно автоматически преобразуется в NULL платформы:
Данные = JSON.Прочитать('{"field": null}');
Сообщить(ЗначениеПустое(Данные.field)); // Истина
В XML ситуация сложнее: пустые элементы могут передаваться разными способами:
- 📌
<field/>— пустой элемент (часто интерпретируется какNULL) - 📌
<field></field>— элемент с пустым содержимым (может стать пустой строкой) - 📌
<field xsi:nil="true"/>— явное указание наNULL(требует настройки XSD-схемы)
Для корректной обработки рекомендуется:
- Настраивать XDTO-пакеты с явным указанием типов данных.
- Использовать
ЗначениеПустое()для проверки прочитанных значений. - При записи в JSON/XML явно указывать
NULLчерезНеопределено:JSON.Записать(Неопределено); // Сериализуется в null
Явно указаны типы данных в XDTO-пакетах|Используется ЗначениеПустое() для проверки входящих значений|Тестируется обработка пустых элементов XML|Проверяется сериализация NULL в JSON-->
Оптимизация запросов с условиями на NULL
Условия с NULL в запросах могут значительно влиять на производительность, особенно при работе с большими таблицами. Вот ключевые рекомендации по оптимизации:
1. Избегайте ЗНАЧЕНИЕ в условиях ГДЕ:
Конструкции вида ГДЕ ЗНАЧЕНИЕ(Поле, 0) = 0 вынуждают СУБД выполнять функцию для каждой строки, что блокирует использование индексов. Лучше разделить условие:
ВЫБРАТЬ
Поле1
ИЗ
Таблица
ГДЕ
Поле ЕСТЬ NULL
ИЛИ Поле = 0
2. Используйте индексы по полям с частыми проверками на NULL:
Если поле часто фильтруется по ЕСТЬ NULL, убедитесь, что на нём создан индекс. В 1С индексы автоматически создаются для ссылочных полей, но для примитивных типов (например, Строка) их может не быть.
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 Тогда не работает?
Потому что в 1С (как и в SQL) прямое сравнение с NULL всегда возвращает Ложь. Для проверки на NULL используйте функции ЗначениеПустое() или ЗначениеЗаполнено(), а в запросах — операторы ЕСТЬ NULL/НЕ ЕСТЬ NULL.
Как отличить NULL от пустой строки?
NULL — это отсутствие значения, а пустая строка ("") — это инициализированное значение. Используйте:
Если ЗначениеПустое(Значение) Тогда
// NULL
ИначеЕсли Значение = "" Тогда
// Пустая строка
КонецЕсли;
Можно ли в 1С создать переменную со значением NULL?
Да, с помощью ключевого слова Неопределено:
Переменная = Неопределено;
Это эквивалент NULL на встроенном языке.
Как передать NULL в параметр запроса?
Используйте Неопределено:
Запрос.УстановитьПараметр("Параметр", Неопределено);
В тексте запроса параметр можно сравнивать с NULL через ЕСТЬ NULL.
Почему после десериализации JSON поле стало NULL?
Это происходит, если:
- В JSON поле было
null. - Поле отсутствовало в JSON, а в 1С не было значения по умолчанию.
- Тип данных в 1С не совпал с типом в JSON (например, число вместо строки).
Проверяйте структуру JSON и настройки XDTO.