Документа уже нет, а его записи в регистрах остались: как навести порядок
Содержание
Движения удалённого документа в 1С 8.3 убирают двумя штатными способами. Первый — «Тестирование и исправление» в Конфигураторе с режимом «Создавать объекты»: платформа создаст на месте потерянного документа пустую заглушку, её помечают на удаление и удаляют, а вместе с ней уходят и все записи в регистрах. Второй — записать пустой набор записей с отбором по битому регистратору из внешней обработки. SQL нужен только тогда, когда оба способа не срабатывают.
Узнать такие записи легко: в отчётах и списках регистров вместо документа стоит <Объект не найден> (85:b3f1...). Остатки при этом «плывут»: на складе числится товар, которого нет, а в оборотно-сальдовой ведомости висит сумма без первичного документа.
Почему у документа, которого нет, остались движения
Штатно платформа не оставляет «сирот». При удалении документа она сама удаляет все наборы записей регистров, где этот документ указан регистратором. Неважно, удалили его через обработку удаления помеченных объектов или напрямую: записи уходят вместе с ним.
Значит, документ исчез в обход этого механизма. Вероятные причины:
- 🔄 Сбой обмена. В распределённой базе и в обменах наборы записей регистров передаются отдельно от самих документов. Если пакет дошёл частично, в базе-приёмнике оказываются движения без регистратора.
- 📥 Загрузка данных из файла. Перенос через универсальные обработки выгрузки и загрузки XML позволяет загрузить записи регистров без документов, если их выбрали в разных наборах.
- 🗄️ Правка на уровне СУБД. Кто-то удалил строки из таблицы документов прямым SQL-запросом или восстановил часть таблиц из старой копии.
- 💥 Повреждение базы. Аварийное выключение сервера, сбой диска, обрыв сети при записи в файловую базу .
Похожая ситуация бывает и с живым документом: он не проведён, а записи в регистрах есть. Это другой случай. Документ на месте, достаточно провести его и отменить проведение, либо пометить на удаление: при установке пометки проведённый документ теряет проведение, и движения стираются.
Как найти «висящие» записи регистров
Сначала оцените масштаб: сколько таких регистраторов и в каких регистрах. От этого зависит способ.
Через список регистра в «Все функции»
- Включите команду «Все функции»: главное меню (кнопка ☰ в левом верхнем углу) →
Сервис → Параметры→ флажок «Отображать команду “Все функции”». - Откройте
Все функции → Регистры накопления(илиРегистры сведений,Регистры бухгалтерии) и нужный регистр. - Отсортируйте список по колонке «Регистратор». Строки с текстом
<Объект не найден>и есть ваши записи.
Удалить их отсюда нельзя: записи, подчинённые регистратору, редактируются только через сам документ. Список годится, чтобы убедиться, что проблема есть.
Запросом в консоли запросов
Если регистров много, быстрее запрос. Откройте любую консоль запросов (внешнюю обработку ) и выполните:
ВЫБРАТЬ РАЗЛИЧНЫЕ
Т.Регистратор КАК Регистратор
ИЗ
РегистрНакопления.ТоварыНаСкладах КАК Т
ГДЕ
Т.Регистратор.Дата ЕСТЬ NULL
Приём простой: у любого документа есть реквизит Дата. Если документа в базе нет, обращение через точку возвращает NULL. Подставьте имя своего регистра; для регистра бухгалтерии в БП 3.0 это РегистрБухгалтерии.Хозрасчетный.
Сохраните результат запроса в табличный документ. Список «битых» ссылок пригодится, чтобы после чистки сравнить, что именно было удалено.
Способ 1. Удаление движений через тестирование базы и документ-заглушку
Самый безопасный путь: всё делает платформа, код писать не нужно.
Перед запуском сделайте резервную копию базы
— выгрузку .dt через Администрирование → Выгрузить информационную базу в Конфигураторе или бэкап средствами СУБД для клиент-серверного варианта. Тестированию нужен монопольный доступ: все пользователи должны выйти из базы, работу назначайте на вечер или выходной.
Шаг 1. Запустите тестирование с созданием объектов
- Откройте базу в режиме Конфигуратора.
- Меню
Администрирование → Тестирование и исправление. - Отметьте «Проверка логической целостности информационной базы» и «Проверка ссылочной целостности информационной базы».
- Переключатель «Тестирование и исправление» (не «Только тестирование»).
- В строке «При наличии ссылок на несуществующие объекты» выберите «Создавать объекты».
- Нажмите «Выполнить» и дождитесь окончания. В журнале проверки появятся строки о созданных объектах.
Режим «Создавать объекты» работает на всю базу. Платформа создаст заглушки для всех битых ссылок, в том числе в справочниках и реквизитах документов. Посмотрите журнал проверки: если созданных объектов сотни, лучше перейти к способу 2 и чистить только регистры.
Вариант «Очищать ссылки» здесь не подходит. Он обнуляет поле регистратора, но запись в регистре остаётся, и найти её потом ещё сложнее.
Шаг 2. Найдите и удалите заглушку
- Запустите базу в режиме 1С:Предприятие.
- Откройте журнал документов того вида, который потерялся. Если вид неизвестен, посмотрите в журнале проверки: там указан тип созданного объекта.
- У заглушки пустые реквизиты и пустая дата. При сортировке списка по дате она окажется в самом начале.
- Пометьте её на удаление.
- Удалите помеченные объекты. В БП 3.0 и ЗУП 3.1 путь:
Администрирование → Обслуживание → Удаление помеченных объектов.
Теперь у записей в регистрах есть настоящий регистратор, и при его удалении платформа стирает движения штатно.
Способ 2. Программное удаление движений на языке 1С
Подходит, когда заглушек слишком много, нет монопольного доступа или нужно почистить только конкретные регистры. Суть: для каждого битого регистратора записать в регистр пустой набор записей. Запись пустого набора с замещением стирает все движения этого регистратора.
Код ниже обходит все регистры, подчинённые регистратору: накопления, сведений с режимом записи «Подчинение регистратору», бухгалтерии и расчёта. Разместите его в серверной процедуре внешней обработки и запускайте под пользователем с полными правами.
&НаСервере
Процедура ОчиститьДвиженияУдаленныхНаСервере()
Для Каждого МД Из Метаданные.РегистрыНакопления Цикл
ОчиститьРегистр("РегистрНакопления." + МД.Имя, РегистрыНакопления[МД.Имя]);
КонецЦикла;
РежимПодчинения = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.ПодчинениеРегистратору;
Для Каждого МД Из Метаданные.РегистрыСведений Цикл
Если МД.РежимЗаписи = РежимПодчинения Тогда
ОчиститьРегистр("РегистрСведений." + МД.Имя, РегистрыСведений[МД.Имя]);
КонецЕсли;
КонецЦикла;
Для Каждого МД Из Метаданные.РегистрыБухгалтерии Цикл
ОчиститьРегистр("РегистрБухгалтерии." + МД.Имя, РегистрыБухгалтерии[МД.Имя]);
КонецЦикла;
Для Каждого МД Из Метаданные.РегистрыРасчета Цикл
ОчиститьРегистр("РегистрРасчета." + МД.Имя, РегистрыРасчета[МД.Имя]);
КонецЦикла;
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ОчиститьРегистр(ИмяТаблицы, МенеджерРегистра)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| Т.Регистратор КАК Регистратор
|ИЗ
| " + ИмяТаблицы + " КАК Т
|ГДЕ
| Т.Регистратор.Дата ЕСТЬ NULL";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Набор = МенеджерРегистра.СоздатьНаборЗаписей();
Набор.Отбор.Регистратор.Установить(Выборка.Регистратор);
Набор.ОбменДанными.Загрузка = Истина;
Набор.Записать(Истина);
Сообщить(ИмяТаблицы + ": удалены движения " + Строка(Выборка.Регистратор));
КонецЦикла;
КонецПроцедуры
Что здесь важно:
- 🧩
Набор.Записать(Истина)— параметрИстинаозначает замещение. Пустой набор заменяет всё, что было у регистратора. - 🛡️
ОбменДанными.Загрузка = Истинаотключает обработчикиПередЗаписьюиПриЗаписитиповой конфигурации. Иначе код набора может упасть на проверках, рассчитанных на живой документ. - 📋 Сообщения дают протокол: какие регистраторы и в каких регистрах вычищены.
Сначала прогоните обработку на копии базы. Сравните протокол со списком, который сохранили на этапе поиска: количество регистраторов должно совпасть.
Если нужно удалить движения одного конкретного регистратора, а не всех битых, отбор по запросу не нужен. Получите ссылку из списка регистра (скопируйте значение колонки «Регистратор») и подставьте её в Набор.Отбор.Регистратор.Установить(...).
Способ 3. Удаление через SQL: крайний случай
Прямая правка таблиц идёт в обход платформы. Фирма 1С такой способ не поддерживает, и при проблемах после него на типовую поддержку рассчитывать нельзя. Прибегайте к SQL, только если база не открывается в Предприятии, а тестирование падает с ошибкой на этих записях.
Как узнать имена таблиц
В базе 1С регистры хранятся в таблицах вида _AccumRg1234, документы — _Document567. Соответствие имён покажет функция ПолучитьСтруктуруХраненияБазыДанных(): выполните её в той же внешней обработке и выведите колонки «ИмяТаблицы» и «ИмяТаблицыХранения».
Ссылка на регистратор лежит в поле _RecorderRRef. Если регистратором могут быть документы нескольких видов, рядом есть поле _RecorderTRef с кодом типа.
Пример запроса для MS SQL
Для регистра, где регистратор — документ одного вида:
BEGIN TRAN;
DELETE r
FROM _AccumRg1234 AS r
WHERE NOT EXISTS (
SELECT 1 FROM _Document567 AS d
WHERE d._IDRRef = r._RecorderRRef
);
-- проверьте число удалённых строк, затем COMMIT или ROLLBACK
Только на остановленной базе и после полного бэкапа СУБД. Перед удалением завершите сеансы пользователей в консоли администрирования кластера и запретите новые подключения: работа всех, кто в базе, будет прервана.
Таблицы итогов регистра (_AccumRgT...) этот запрос не трогает. После SQL-правки обязателен пересчёт итогов, иначе отчёты покажут старые остатки.
Сравнение способов
| Способ | Когда подходит | Риски |
|---|---|---|
| Тестирование + заглушка | Битых регистраторов немного, есть окно для монопольного доступа | Заглушки появятся для всех битых ссылок базы |
| Код 1С | Много записей, нужна точечная чистка регистров | Ошибка в отборе сотрёт движения живых документов |
| SQL | База не открывается, платформенные способы падают | Обход платформы, ручной пересчёт итогов, нет поддержки |
Проверка после чистки и пересчёт итогов
Удалить записи мало: нужно убедиться, что остатки сошлись.
- Повторите поисковый запрос. Для каждого регистра он должен вернуть пустой результат.
- Пересчитайте итоги. В Предприятии:
Все функции → Стандартные → Управление итогами, режим полных возможностей, кнопка пересчёта итогов. В Конфигураторе то же делает пункт «Пересчёт итогов» в окне тестирования и исправления. - Сверьте отчёты. В БП 3.0 сформируйте оборотно-сальдовую ведомость за период, где были битые движения, и сравните с сохранённой до чистки. Разница должна равняться суммам удалённых записей.
- Проверьте закрытые периоды. Если записи были в периоде, за который сдана отчётность, изменение остатков затронет сданные данные. Обсудите с главным бухгалтером, нужно ли уточнение.
В БП и ЗУП после удаления движений в прошлом периоде перепроведите документы с даты первой удалённой записи и повторите закрытие месяца. Иначе себестоимость, остатки по партиям и расчёт зарплаты останутся посчитанными по старым данным.
Если бизнес-смысл удалённого документа был реальным (товар действительно пришёл, оплата действительно была), не ограничивайтесь чисткой: введите документ заново и проведите его.
Как не допустить новых «висящих» движений
- 🔐 Права на непосредственное удаление. Обычным пользователям оставьте только пометку на удаление. Удаление помеченных запускает администратор, когда в базе никого нет.
- 🔄 Контроль обменов. После сбоя синхронизации проверяйте протокол обмена и повторяйте его до полного прохождения пакета. Не загружайте вручную части сообщения обмена.
- 📦 Перенос данных — целиком. При выгрузке через XML выбирайте документы вместе с их движениями или только документы с последующим перепроведением, но не регистры отдельно.
- 🗄️ Никаких правок в СУБД. Любые изменения данных — через платформу. Даже восстановление одной таблицы из копии почти наверняка оставит битые ссылки.
- 🩺 Регулярная проверка. Раз в квартал запускайте тестирование в режиме «Только тестирование» на копии базы. Сообщения о ссылках на несуществующие объекты — сигнал разобраться, пока записей мало.
- 💾 Резервные копии по расписанию. Если битые движения появились после известного события, иногда проще восстановить базу на день раньше и повторить ввод.