В процессе эксплуатации баз данных «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
Если запрос возвращает строки, значит, проблема действительно в битых ссылках. Если же поле регистратора визуально пустое, но запрос ничего не находит, возможно, повреждена структура самих таблиц итогов, и тогда первоочередной мерой должен стать пересчет итогов в Конфигураторе.
Таким образом, мы разобрали основные методы борьбы с некорректными записями. Помните, что любое прямое манипулирование записями регистра — это ответственная операция. Всегда проверяйте алгоритм на копии базы данных перед применением в «боевой» среде.