Каждый специалист по работе с платформой 1С:Предприятие рано или поздно сталкивается с ситуацией, когда после «глобальной чистки» базы данных отчеты по остаткам (сток) начинают вести себя непредсказуемо. В них появляются пустые строки либо пугающие записи вида <Объект не найден> (уникальный идентификатор GUID), напротив которых отображаются вполне реальные цифры остатков и сумм.
В этой статье мы подробно разберем, почему возникает эта проблема, как устроена ссылочная целостность в 1С, и проанализируем по шагам все способы исправления ситуации — от стандартных утилит до написания корректирующего кода.
Для того чтобы понять природу этой ошибки, нам необходимо заглянуть под капот платформы 1С. Когда пользователь удаляет элемент справочника (например, Номенклатуру) или документ, крайне важно делать это через типовой механизм контроля ссылок. Если же удаление происходит напрямую программным методом Удалить() или через сторонние «быстрые» обработки, отключающие проверку связей, данные стираются только из основной таблицы самого объекта.
Однако учет движений товаров, взаиморасчетов и остатков в 1С ведется в специальных физических таблицах — регистрах накопления и регистрах сведений. Записи в этих регистрах хранят не текстовые наименования, а уникальные 128-битные идентификаторы объектов — GUID (UUID).
При «жестком» удалении номенклатуры происходят следующие процессы:
Справочник.Номенклатура полностью физически удаляется из базы данных SQL или файлового хранилища.РегистрНакопления.ТоварыНаСкладах), которые ссылались на этот товар по его GUID, остаются нетронутыми, поскольку проверка связей была отключена.GUID с таблицей справочника Номенклатура, чтобы вывести красивое наименование товара.<Объект не найден> или просто пустую строку, но при этом выводит числовые показатели (остатки), которые «зависли» в регистре. В профессиональной среде такие ссылки называют «битыми».Самым надежным и стандартным способом решения проблемы является использование встроенной утилиты администрирования платформы. Разберем этот процесс по шагам.
Важно: Перед выполнением любых административных процедур в Конфигураторе строго обязательно создайте резервную копию вашей информационной базы! Любые операции по лечению битых ссылок необратимы.
Администрирование — Активные пользователи.Администрирование — Тестирование и исправление....GUID, и в отчетах вместо битых ссылок появятся пустые строки, которые вы сможете заполнить нужными именами.Если база данных имеет огромный объем (сотни гигабайт), запуск полного «Тестирования и исправления» может занять слишком много времени (вплоть до нескольких суток простоя системы). В таких случаях программисты используют точечные программные методы локализации и устранения проблемы.
Рассмотрим, как обнаружить битую ссылку в конкретном регистре накопления с помощью запроса. В языке запросов 1С при попытке обратиться к реквизитам удаленного объекта через точку (например, Номенклатура.Наименование) система вернет значение NULL. Мы можем использовать это свойство для выявления ошибок.
Проанализируем пример кода для поиска битых ссылок в регистре остатков товаров:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ТоварыНаСкладах.Номенклатура КАК БитыйТовар,
| ТоварыНаСкладах.Склад КАК Склад,
| ТоварыНаСкладах.КоличествоОстаток КАК Количество
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки КАК ТоварыНаСкладах
|ГДЕ
| ТоварыНаСкладах.Номенклатура.ВерсияДанных ЕСТЬ NULL
| И ТоварыНаСкладах.Номенклатура <> ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)";
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Здесь мы можем зафиксировать битые ссылки или программно очистить движения
ЗаписьЖурналаРегистрации("ОшибкиДанных", УровеньЖурналаРегистрации.Предупреждение, , ,
"Найден битый товар: " + Выборка.БитыйТовар + " на складе " + Выборка.Склад);
КонецЦикла;
КонецЕсли;
Для исправления таких записей без полного тестирования базы можно использовать специализированные внешние обработки с порталов Инфостарт или встроенные инструменты из состава «Библиотеки стандартных подсистем» (БСП), такие как обработка «Поиск и замена дублей» или «Поиск и удаление битых ссылок». Они позволяют перенаправить все движения с битого GUID на один специально созданный технический элемент справочника (например, элемент с наименованием «Удаленный товар»).
Для того чтобы ситуация не повторилась, необходимо полностью отказаться от практики непосредственного жесткого удаления объектов из базы данных программным путем. Метод Удалить() должен использоваться только в исключительных случаях на этапе отладки или первоначального заполнения пустой базы.
Рассмотрим правильный подход к удалению данных на примере кода. Вместо удаления объекта мы должны лишь устанавливать пометку удаления, позволяя платформе контролировать связи:
// ПРИМЕР НЕПРАВИЛЬНОГО И ОПАСНОГО УДАЛЕНИЯ (вызывает появление битых ссылок):
// СсылкаНаОбъект.ПолучитьОбъект().Удалить();
// ПРИМЕР ПРАВИЛЬНОГО И БЕЗОПАСНОГО УДАЛЕНИЯ:
СсылкаНаНоменклатуру = Справочники.Номенклатура.НайтиПоКоду("0000000125");
Если Не СсылкаНаНоменклатуру.Пустая() Тогда
ОбъектНоменклатуры = СсылкаНаНоменклатуру.ПолучитьОбъект();
// Устанавливаем пометку удаления для самого элемента и его подчиненных структур
ОбъектНоменклатуры.УстановитьПометкуУдаления(Истина, Истина);
ОбъектНоменклатуры.Записать();
КонецЕсли;
После того как все ненужные объекты помечены на удаление, их окончательное физическое удаление должен производить только администратор базы через стандартный интерактивный интерфейс «Удаление помеченных объектов» (в режиме предприятия). Этот механизм гарантирует, что ни один объект не будет удален, если на него ссылается хотя бы один документ, проводка или запись регистра в системе.