В процессе разработки на платформе «1С:Предприятие 8» программисты часто сталкиваются с задачей программной очистки реквизитов объекта. Особенно много вопросов вызывает работа со ссылочными типами данных, такими как справочники, документы или бизнес-процессы. Ошибочные действия, такие как присвоение пустой строки или некорректная работа с составными типами, могут привести к трудночитаемому коду, ошибкам при записи или проблемам с производительностью запросов. Разберем подробно, как правильно очищать ссылки и какие нюансы при этом стоит учитывать.
Разберем типичную ошибку начинающих разработчиков: попытку присвоить ссылочному полю значение пустой строки "". Рассмотрим, почему конструкция Объект.Реквизит = "" является неверной. В системе 1С жесткая типизация. Реквизит типа СправочникСсылка ожидает на входе уникальный 16-байтовый идентификатор (GUID), в то время как "" — это строковый тип данных.
Проанализируем последствия такого присвоения:
Самым универсальным и рекомендуемым способом очистки реквизита является использование системного значения Неопределено. Посмотрим, как это выглядит в коде:
// Правильная очистка реквизита через Неопределено
Объект.Контрагент = Неопределено;
Объект.Договор = Неопределено;
Рассмотрим подробнее, что происходит в этот момент. Если реквизит имеет одиночный тип (например, только СправочникСсылка.Номенклатура), платформа при записи объекта автоматически преобразует Неопределено в пустую ссылку данного типа. Это наиболее безопасный способ, так как он не требует от программиста указывать конкретный тип справочника.
Если же реквизит имеет составной тип данных, использование Неопределено становится критически важным. Выясним причину: когда мы присваиваем Неопределено составному типу, мы полностью очищаем поле и от значения, и от информации о типе. В базе данных такое поле будет храниться как полностью пустое значение.
Иногда логика бизнес-процесса требует, чтобы реквизит оставался «пустым», но при этом сохранял информацию о своем типе. Для этого используются методы менеджеров объектов. Рассмотрим на примере справочника Номенклатура:
// Присвоение конкретной пустой ссылки
Объект.Товар = Справочники.Номенклатура.ПустаяСсылка();
Проанализируем ситуацию, когда это необходимо. В составных типах данных (например, «Владелец», который может быть и Контрагентом, и Физическим лицом), присвоение Справочники.Контрагенты.ПустаяСсылка() скажет системе: «Здесь не выбран конкретный контрагент, но мы ожидаем именно контрагента».
Однако, как отметили участники обсуждения, в большинстве случаев для составных типов лучше использовать Неопределено. Если вы установите пустую ссылку конкретного типа в поле из 100 возможных типов документов, это может усложнить написание запросов, где придется проверять каждое конкретное пустое значение вместо одной проверки на НЕОПРЕДЕЛЕНО.
Выяснив, как устанавливать пустое значение, разберем, как его правильно проверять. Использование метода Объект.Реквизит.Пустая() имеет одну существенную опасность. Если в реквизите окажется значение Неопределено, вызов метода .Пустая() приведет к фатальной ошибке «Метод объекта не обнаружен».
Посмотрим на более надежный и универсальный способ проверки — функцию ЗначениеЗаполнено():
// Безопасная проверка любого типа реквизита
Если ЗначениеЗаполнено(Объект.Склад) Тогда
// Выполняем действия, если склад выбран
Иначе
// Действия, если поле пустое (пустая ссылка, Неопределено, NULL или 0)
Сообщить("Склад не заполнен!");
КонецЕсли;
Эта функция является предпочтительной, так как она корректно обрабатывает все варианты «пустоты»:
Неопределено;NULL (часто встречается в результатах запросов);Проанализируем, как работать с очищенными полями внутри запросов 1С. Это важная часть, так как синтаксис здесь отличается от встроенного языка. Для проверки на пустую ссылку конкретного типа в запросе следует использовать конструкцию ЗНАЧЕНИЕ.
Разберем пример кода запроса:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Реализация.Ссылка КАК Документ
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Реализация
|ГДЕ
| Реализация.Контрагент = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)";
Если же мы работаем с составным типом и хотим найти записи, где поле было очищено через Неопределено, мы используем соответствующее ключевое слово:
Запрос.Текст =
"ВЫБРАТЬ
| Заказы.Ссылка
|ИЗ
| Документ.ЗаказПокупателя КАК Заказы
|ГДЕ
| Заказы.Проект = НЕОПРЕДЕЛЕНО";
Важный момент: никогда не используйте ЕСТЬ NULL для проверки обычных пустых реквизитов. NULL в 1С появляется только при выполнении соединений таблиц, когда в правой (или левой) таблице не найдена соответствующая запись. В обычных полях объекта NULL не хранится.
Для глубокого понимания процесса заглянем «под капот» системы. На уровне SQL-сервера (будь то MS SQL или PostgreSQL) пустая ссылка представляет собой уникальный идентификатор, состоящий из одних нулей: 00000000-0000-0000-0000-000000000000.
Когда вы используете составной тип, платформа создает в таблице несколько физических колонок для одного реквизита 1С (например, колонку для типа и колонку для самого значения ссылки). Если вы используете Неопределено, система записывает в колонку типа специальный маркер отсутствия типа. Это позволяет базе данных работать быстрее при индексации и поиске, так как уменьшается количество «ложных» типизированных пустых ссылок.
Подведем итог нашему разбору. Правильная работа с очисткой данных — это залог стабильности вашей конфигурации.
Сформулируем основные правила:
Объект.Реквизит = Неопределено;. Это самый универсальный и безопасный путь..Ссылка при очистке (например, Объект.Реквизит.Ссылка = ...). Это избыточно и может привести к ошибкам, так как свойство Ссылка у объектов обычно доступно только для чтения.Справочники.Имя.ПустаяСсылка().ЗначениеЗаполнено() вместо сравнения с пустой ссылкой или вызова метода .Пустая().ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка) или НЕОПРЕДЕЛЕНО в зависимости от того, как поле было очищено и какой тип оно имеет.Следуя этим правилам, вы обеспечите корректную работу программы как в интерфейсе, так и на уровне базы данных, избежите лишних ошибок и сделаете ваш код понятным для других разработчиков.