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