Администрирование · 11 мин
Как удалить битую ссылку в 1С программно
Как программно найти и удалить битые ссылки в 1С: проверка ПолучитьОбъект, обработка очистки ссылок, код для справочников, документов и регистров.
Битая ссылка в 1С — это ссылка на объект, которого уже нет в базе: элемент справочника, документ или запись были удалены, а ссылки на них остались в реквизитах других объектов, в табличных частях и в регистрах. В запросах такие ссылки отображаются как «Объект не найден» с длинным шестнадцатеричным идентификатором, а при попытке открыть их интерактивно платформа выдаёт ошибку.
Программное удаление битых ссылок сводится к двум задачам: найти все места, где они хранятся, и очистить эти места безопасным способом. В типовых конфигурациях есть штатный механизм удаления помеченных объектов, который умеет делать это автоматически, но в нестандартных ситуациях — после обменов, прямой загрузки данных, сбоев — требуется собственная обработка.
Ниже разобраны способы определения битой ссылки в коде, готовые процедуры поиска по всем метаданным, варианты очистки и типичные ошибки, которые приводят к потере данных.
Что такое битая ссылка и откуда она берётся
Каждый объект ссылочного типа в 1С имеет уникальный идентификатор (GUID). Когда объект удаляется физически, а ссылки на него остаются, платформа не может материализовать объект по идентификатору — и возникает «битая» ссылка. Технически это значение с типом ссылки, у которого запрос к базе не возвращает ни одной записи.
Основные источники битых ссылок: удаление объектов напрямую без контроля ссылочной целостности (режим «Удалить» вместо пометки), обмены данными, где объект-ссылка не выгрузился или не загрузился, восстановление из неполной копии, штатная обработка удаления помеченных, прерванная на середине, а также прямые правки в СУБД, чего делать категорически нельзя.
Как определить битую ссылку в коде
Универсальный способ проверки — попытка получить объект по ссылке. Если объект физически отсутствует, метод ПолучитьОбъект() вернёт Неопределено. Дополнительно полезно проверять, что ссылка вообще заполнена, чтобы не путать пустое значение с битым.
Функция ЭтоБитаяСсылка(ПроверяемаяСсылка) Экспорт
Если Не ЗначениеЗаполнено(ПроверяемаяСсылка) Тогда
Возврат Ложь; // пустая ссылка — не битая
КонецЕсли;
Возврат ПроверяемаяСсылка.ПолучитьОбъект() = Неопределено;
КонецФункции
Для массовой проверки вызывать ПолучитьОбъект() в цикле дорого: каждый вызов — обращение к базе. Быстрее собрать ссылки в таблицу значений и проверить их одним запросом через левое соединение: если присоединённая таблица дала NULL, объекта нет.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Таб.Ссылка КАК Ссылка
|ПОМЕСТИТЬ ВТ_Ссылки
|ИЗ &ТаблицаСсылок КАК Таб
|;
|ВЫБРАТЬ
| ВТ_Ссылки.Ссылка КАК БитаяСсылка
|ИЗ ВТ_Ссылки КАК ВТ_Ссылки
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Ном
| ПО ВТ_Ссылки.Ссылка = Ном.Ссылка
|ГДЕ Ном.Ссылка ЕСТЬ NULL";
Запрос.УстановитьПараметр("ТаблицаСсылок", ТаблицаСсылок);
Способ 1. Штатное удаление помеченных объектов
Прежде чем писать код, проверьте штатный механизм. В режиме «Удаление помеченных объектов» (в типовых конфигурациях — раздел «Администрирование») платформа при выборе варианта «Выборочное удаление» показывает все объекты, которые мешают удалению, и предлагает очистить ссылки на удаляемые объекты в найденных местах. Это самый безопасный путь: платформа сама знает все места использования.
Программно эту логику можно запустить через метод глобального контекста УдалитьПомеченныеОбъекты() в монопольном режиме. Метод удалит помеченные объекты, а в местах использования либо очистит ссылки, либо вернёт список препятствий, если удаление невозможно.
- 1Сделайте резервную копию информационной базы
- 2Пометьте на удаление объекты, ссылки на которые стали битыми (если они ещё существуют)
- 3Запустите «Удаление помеченных объектов» в монопольном режиме
- 4Просмотрите список препятствий и обработайте проблемные места вручную
- 5Повторите удаление и проверьте отсутствие «Объект не найден» в отчётах
Способ 2. Поиск мест использования через НайтиПоСсылкам
Когда известна конкретная битая ссылка, все места её хранения находит метод НайтиПоСсылкам(). Он возвращает таблицу значений с колонками «Ссылка» (что искали), «Данные» (объект, где найдено) и «Метаданные» (где именно). Дальше по каждой строке принимается решение: очистить реквизит, удалить строку табличной части или удалить запись регистра.
МассивСсылок = Новый Массив;
МассивСсылок.Добавить(БитаяСсылка);
МестаИспользования = НайтиПоСсылкам(МассивСсылок);
Для Каждого Место Из МестаИспользования Цикл
ОбъектДанных = Место.Данные.ПолучитьОбъект();
// дальше — анализ, в каком реквизите сидит ссылка,
// и его очистка с последующей записью
КонецЦикла;
Ограничение метода — производительность: он сканирует все таблицы, где может встретиться ссылка данного типа. На больших базах запускайте поиск порциями и в нерабочее время.
Способ 3. Полный перебор метаданных и очистка реквизитов
Если битых ссылок много и их источники неизвестны, пишут универсальную обработку: перебираются справочники, документы и их реквизиты ссылочных типов, значения проверяются, битые очищаются. Ниже упрощённый каркас такой обработки для справочников.
Для Каждого МетаСпр Из Метаданные.Справочники Цикл
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Таб.Ссылка ИЗ Справочник."
+ МетаСпр.Имя + " КАК Таб";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Объект = Выборка.Ссылка.ПолучитьОбъект();
Изменён = Ложь;
Для Каждого Реквизит Из МетаСпр.Реквизиты Цикл
Значение = Объект[Реквизит.Имя];
Если ЗначениеЗаполнено(Значение)
И ЭтоСсылочныйТип(Значение)
И Значение.ПолучитьОбъект() = Неопределено Тогда
Объект[Реквизит.Имя] = Неопределено;
Изменён = Истина;
КонецЕсли;
КонецЦикла;
Если Изменён Тогда
Объект.ОбменДанными.Загрузка = Истина;
Объект.Записать();
КонецЕсли;
КонецЦикла;
КонецЦикла;
Функция ЭтоСсылочныйТип проверяет, что значение — ссылка, а не примитивный тип: проще всего через ТипЗнч() и сравнение с описанием типов реквизита, либо через попытку обращения к свойству ссылки. Обратите внимание на ОбменДанными.Загрузка = Истина — запись без проверок и бизнес-логики. Это ускоряет обработку, но отключает контроль, поэтому применяйте осознанно.
Отдельно обрабатывайте табличные части (там битую ссылку чаще не очищают, а удаляют строку целиком), регистры сведений (записи с битой ссылкой в измерении обычно удаляют) и движения документов. Для регистров сведений с независимым режимом запись с битым измерением находится запросом и удаляется через набор записей с отбором.
Проверка результата и тестирование целостности
После очистки убедитесь, что битых ссылок не осталось и не появились новые. Быстрый способ — построить универсальный отчёт или запрос по проблемным таблицам и проверить отсутствие значений вида «Объект не найден». Для файловых баз дополнительно выполните «Тестирование и исправление» (chdbfl для файловой базы или конфигуратор) с включённой проверкой ссылочной целостности — но только в режиме «Тестирование» без исправления, чтобы сначала увидеть список проблем.
Признаки успешной очистки: отчёты и подборы открываются без ошибок, запросы с соединениями не возвращают строк с NULL там, где раньше были битые ссылки, обмены данными завершаются без ошибок разрешения коллизий по несуществующим объектам.
Как проверить результат
Нет строк с «Объект не найден»
Ссылки с идентификатором остались
Формы открываются без ошибок
Ошибка «Объект не найден» при открытии
Проверка целостности без замечаний
Найдены ссылки на несуществующие объекты
Типичные ошибки при программной очистке
Самая частая ошибка — очистка ссылки вместо удаления строки там, где ссылка обязательна. Например, если в табличной части документа очистить колонку «Номенклатура», документ станет некорректным по смыслу; правильнее удалить строку или пометить документ на удаление. Вторая ошибка — обработка только реквизитов шапки и игнорирование табличных частей, регистров и последовательностей.
Третья группа ошибок — техническая: запуск обработки без монопольного режима (часть объектов не запишется из-за блокировок), отсутствие транзакции при пакетной записи и забытый ОбменДанными.Загрузка там, где он нужен, — или наоборот, его использование там, где нужна бизнес-логика записи.
Частые вопросы
Чем битая ссылка отличается от пустой?
Пустая ссылка — это корректное значение «ничего не выбрано», она существует и равна пустой ссылке своего типа. Битая ссылка формально заполнена, но объекта с таким идентификатором в базе нет. Проверка ЗначениеЗаполнено() для битой ссылки вернёт Истина, поэтому отличать их нужно через ПолучитьОбъект() = Неопределено.
Можно ли восстановить объект по битой ссылке, а не удалять её?
Да, если известен GUID. Можно программно создать новый объект и установить ему ссылку с нужным идентификатором через Справочники.Имя.ПолучитьСсылку(Новый УникальныйИдентификатор("...")) и запись объекта по этой ссылке. Так делают, когда объект потерян при обмене, а ссылки на него ценны.
Почему «Удаление помеченных объектов» не удаляет объект?
Платформа показывает список мест, где объект используется, и блокирует удаление, если ссылки нельзя очистить автоматически — например, объект указан в измерении регистра или в критичном реквизите. Нужно выборочно разрешить очистку в найденных местах или обработать их вручную, после чего повторить удаление.
Опасно ли ставить ОбменДанными.Загрузка = Истина при записи?
Само по себе — нет, это стандартный приём для сервисных обработок. Опасность в том, что отключаются проверки заполнения, подписки на события и бизнес-логика: если ваша обработка ошибочно меняет данные, ничто её не остановит. Поэтому сначала делается прогон без записи, а запись включается после проверки списка изменений.
Как найти битые ссылки во всей базе сразу, а не по одному справочнику?
Пишется обработка с перебором коллекций метаданных: справочники, документы, планы видов характеристик, планы счетов, их реквизиты и табличные части, а также регистры сведений. Для каждого ссылочного поля выполняется запрос с левым соединением и условием IS NULL. Готовые универсальные обработки часто включают в состав инструментов администратора.
Нужно ли после очистки запускать «Тестирование и исправление»?
Желательно, но в режиме только проверки. Программная очистка правит данные на прикладном уровне, а «Тестирование и исправление» контролирует физическую целостность таблиц и индексов. Проверка подтвердит, что не осталось ссылок на несуществующие объекты и структура базы не повреждена.
Что важно запомнить
Битая ссылка определяется через ПолучитьОбъект() = Неопределено. Сначала используйте штатное удаление помеченных объектов, программную обработку — при массовых повреждениях. Перед записью делайте копию, прогон без изменений и монопольный режим, после — проверяйте целостность базы.