В процессе разработки на платформе 1С:Предприятие 8 программисты часто сталкиваются с необходимостью обработки "пустых" данных. Возникает закономерный вопрос: как правильно работать с типом NULL, можно ли его присвоить переменной или реквизиту объекта и чем он принципиально отличается от привычного Неопределено. В рамках данной статьи мы подробно разберем природу этого типа, проанализируем его поведение в программном коде и выясним, как система ведет себя при попытке записи NULL в базу данных.
Для начала давайте разберем фундаментальное различие. NULL — это специальный тип данных, который в контексте 1С означает отсутствие значения как такового. Важно понимать, что NULL не является эквивалентом нуля, пустой строки или ссылки. В то время как Неопределено используется для обозначения пустого значения в переменных или реквизитах составного типа (когда тип еще не выбран или явно сброшен), NULL чаще всего появляется как результат работы запросов, например, при выполнении левого соединения, когда во второй таблице не найдена соответствующая запись.
Рассмотрим ситуацию в коде. Мы можем напрямую присвоить литерал NULL переменной, и она действительно примет этот тип. Проанализируем пример кода:
ПеременнаяХ = NULL;
Если ТипЗнч(ПеременнаяХ) = Тип("NULL") Тогда
Сообщить("В переменной действительно содержится NULL");
КонецЕсли;
Однако стоит помнить, что NULL — это синглтон, то есть в системе существует только один экземпляр этого значения. С точки зрения логики, NULL не равен ничему, даже самому себе. Это критически важный момент для написания алгоритмов.
Многие разработчики пытаются "очистить" поле реквизита в справочнике или документе, присваивая ему NULL. Разберем по шагам, что произойдет в этом случае. Посмотрим на типовой сценарий:
Объект.Реквизит = NULL;NULL.Записать() платформа 1С производит маршалинг данных для сохранения в SQL-таблицу.NULL на уровне базы данных, система автоматически преобразует его.Важный вывод: если реквизит имеет простой тип (например, СправочникСсылка), при записи NULL превратится в ПустуюСсылку. Если реквизит имеет составной тип данных, он преобразуется в Неопределено. Таким образом, "заставить" базу данных хранить NULL в стандартном реквизите штатными средствами встроенного языка невозможно.
Проанализируем ситуацию, в которой NULL является естественным результатом. Чаще всего это происходит в запросах. Рассмотрим пример левого соединения справочника Номенклатура с остатками на складах:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Товар,
| ЕСТЬNULL(ТоварыНаСкладахОстатки.КоличествоОстаток, 0) КАК Остаток
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК ТоварыНаСкладахОстатки
| ПО Номенклатура.Ссылка = ТоварыНаСкладахОстатки.Номенклатура";
В этом примере мы используем функцию ЕСТЬNULL, чтобы заменить "пустоту" на числовое значение 0. Если этого не сделать, и записи в регистре не будет, поле КоличествоОстаток вернет NULL. При попытке сложить такое значение с числом в коде 1С мы получим ошибку несовпадения типов.
Единственное исключение из правил хранения — это механизм Внешних источников данных. Если вы подключаетесь к сторонней базе данных (SQL Server, PostgreSQL и др.), где таблицы были созданы вне 1С, и колонки этих таблиц поддерживают состояние is null, то 1С позволит с ними работать.
В этом случае при чтении данных через ОбъектМетаданных.ВнешниеИсточникиДанных вы действительно увидите тип NULL. Более того, при записи в такие таблицы платформа корректно передаст NULL в SQL-запрос INSERT или UPDATE, если соответствующее поле объекта в коде было установлено в NULL.
Выясним причину, по которой классическое сравнение Переменная = NULL может работать не так, как ожидается. В 1С (как и в SQL) применяется трехзначная логика. Посмотрим на примеры:
Результат1 = (NULL = NULL); // Ложь
Результат2 = (NULL <> NULL); // Ложь
Результат3 = (NULL = Неопределено); // Ложь
Как мы видим, NULL нельзя сравнивать через операторы равенства. Чтобы проверить, содержит ли переменная NULL, всегда используйте один из двух способов:
Если ТипЗнч(Значение) = Тип("NULL") Тогда...Если НЕ ЗначениеЗаполнено(Значение) Тогда... (учтите, что эта функция вернет Ложь также для пустых ссылок и Неопределено).Часто возникает вопрос о присвоении NULL в субконто регистра бухгалтерии. Рассмотрим ситуацию: если счет не предполагает использования определенного вида субконто, система при чтении данных через запрос вернет NULL для этого измерения. Однако при программной записи движений вы должны использовать Неопределено или пустую ссылку соответствующего типа. Попытка записать NULL в субконто приведет к тому, что платформа подставит значение по умолчанию, что может привести к "разъезжанию" остатков, если в других документах использовалось Неопределено.
Подведем итог: использовать NULL в коде для обозначения отсутствия данных можно, это помогает отделять "неинициализированные" данные от "отсутствующих". Однако всегда помните, что при сохранении в стандартные таблицы БД это значение не сохранится в первозданном виде. Для надежной работы алгоритмов всегда делайте проверку через ТипЗнч() и грамотно используйте функцию запроса ЕСТЬNULL.