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