В процессе эксплуатации баз данных «1С:Предприятие 8» иногда возникают ситуации, когда в регистрах накопления появляются «записи-призраки». Это движения, у которых в поле Регистратор отображается надпись «Объект не найден (номер:УИД)». Такие записи не только искажают остатки и обороты, но и могут приводить к критическим ошибкам при обмене данными (РИБ) или проведении документов. Рассмотрим подробно, почему это происходит и как правильно очистить регистр от подобных записей — для этого есть утилита удаления битых ссылок в регистрах без тестирования базы.
Прежде чем приступать к удалению, важно понять природу проблемы. Ссылка «Объект не найден» означает, что в таблице регистра накопления существует запись с определенным уникальным идентификатором (GUID) регистратора, но в основной таблице документов (например, Документ.РеализацияТоваровУслуг) объекта с таким GUID больше нет. Это могло произойти из-за сбоя при удалении документа, некорректной работы правил обмена или прямого вмешательства в базу данных на уровне SQL.
Это самый простой и штатный способ, не требующий написания кода. Проанализируем, как настроить этот инструмент для нашей задачи:
Важный момент: Тестирование и исправление — это мощный инструмент, который затрагивает всю базу. Перед его использованием обязательно создайте резервную копию. Если вы не хотите трогать другие объекты, лучше воспользоваться программными методами — для этого подойдёт набор обработок очистки базы от битых движений.
Если вам нужно удалить конкретную запись, зная её идентификатор (например, 55:98180080485e404011e1981c0af3e8ae), можно восстановить ссылку программно — для этого есть инструмент ручного исправления и редактирования записей регистров. Разберем этот метод по шагам.
Сначала нам нужно определить тип документа. После этого мы можем получить внутреннее представление ссылки. Посмотрим на пример кода, который преобразует строковый идентификатор в полноценную ссылку 1С:
// Определяем пустую ссылку нужного типа документа
ПустаяСсылкаДокумента = Документы.РеализацияТоваровУслуг.ПустаяСсылка();
// Получаем внутреннюю строку для этого типа
ВнутрСтрока = ЗначениеВСтрокуВнутр(ПустаяСсылкаДокумента);
// В полученной строке вида {"#",13dbeddc...,356:0000...}
// заменяем нулевой идентификатор на наш "битый" ID
НоваяСтрока = СтрЗаменить(ВнутрСтрока, "356:00000000000000000000000000000000", "55:98180080485e404011e1981c0af3e8ae");
// Преобразуем обратно в ссылку
РегистраторСсылка = ЗначениеИзСтрокиВнутр(НоваяСтрока);
// Теперь очищаем набор записей по этому регистратору
НаборЗаписей = РегистрыНакопления.ТоварыНаСкладах.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(РегистраторСсылка);
НаборЗаписей.Записать(); // Запись пустого набора удаляет движения
Проанализируем наиболее эффективный способ, который позволяет найти сразу все битые записи в конкретном регистре и удалить их — процесс ускоряет обработка автоматической диагностики и удаления битых ссылок. Этот метод использует язык запросов 1С для поиска записей, где ссылка на регистратор равна NULL.
Рассмотрим пример обработки:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| ТоварыНаСкладах.Регистратор КАК Регистратор
|ИЗ
| РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах
|ГДЕ
| ТоварыНаСкладах.Регистратор.Ссылка ЕСТЬ NULL";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Создаем набор записей для каждого найденного "битого" регистратора
НЗ = РегистрыНакопления.ТоварыНаСкладах.СоздатьНаборЗаписей();
НЗ.Отбор.Регистратор.Установить(Выборка.Регистратор);
// Используем ОбменДанными.Загрузка для обхода проверок
НЗ.ОбменДанными.Загрузка = Истина;
Попытка
НЗ.Записать();
Сообщить("Записи по регистратору " + Выборка.Регистратор + " успешно удалены.");
Исключение
Сообщить("Не удалось удалить записи: " + ОписаниеОшибки());
КонецПопытки;
// Позволяет пользователю прервать процесс нажатием Ctrl+Break
ОбработкаПрерыванияПользователя();
КонецЦикла;
Рассмотрим дополнительные технические аспекты, которые помогут избежать ошибок при очистке:
ОбменДанными.Загрузка: Всегда устанавливайте его в значение Истина перед выполнением метода Записать(). Это позволит избежать срабатывания подписок на события и проверок (например, даты запрета редактирования), что значительно ускорит процесс и предотвратит блокировки.Активность у записи в одной базе отличается от флага в другой. Чтобы исправить это, нужно прочитать набор записей, принудительно установить Запись.Активность = Истина (или Ложь) для всех строк и перепровести набор, после чего выполнить обмен.RecordSet отказывается работать, это может означать, что поле Регистратор в базе данных физически пустое. В таком случае поможет только полное «Тестирование и исправление» или (в крайнем случае для серверных баз) использование SQL-запроса DELETE.Перед тем как удалять данные, мы рекомендуем проанализировать их масштаб — для этого подойдёт набор технических инструментов и консоль запросов 1С. Откройте консоль запросов и выполните следующий код:
ВЫБРАТЬ
ПРЕДСТАВЛЕНИЕ(ТоварыНаСкладах.Регистратор),
ТоварыНаСкладах.Регистратор,
Период,
НомерСтроки
ИЗ
РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах
ГДЕ
ТоварыНаСкладах.Регистратор.Ссылка ЕСТЬ NULL
Если запрос возвращает строки, значит, проблема действительно в битых ссылках. Если же поле регистратора визуально пустое, но запрос ничего не находит, возможно, повреждена структура самих таблиц итогов, и тогда первоочередной мерой должен стать пересчет итогов в Конфигураторе.
Таким образом, мы разобрали основные методы борьбы с некорректными записями. Помните, что любое прямое манипулирование записями регистра — это ответственная операция. Всегда проверяйте алгоритм на копии базы данных перед применением в «боевой» среде.