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