Что происходит с подчиненными справочниками при удалении владельца в 1С и как правильно реализовать каскадное удаление?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

В процессе разработки и администрирования баз данных на платформе 1С:Предприятие (начиная с классической версии 7.7 и заканчивая современными редакциями 8.3) одной из наиболее важных тем является сохранение ссылочной целостности данных. Часто у начинающих разработчиков возникает вопрос: что произойдет с элементами подчиненного справочника «Б», если физически удалить его владельца — элемент справочника «А»?

В этой статье мы подробно разберем внутренние механизмы работы платформы 1С при удалении связанных данных, выясним причину появления так называемых «битых ссылок», научимся правильно писать код для каскадного удаления и рассмотрим способы исправления уже возникших ошибок в базе данных.

Физика процесса: что происходит «под капотом» базы данных?

Для того чтобы понять последствия удаления, давайте заглянем на уровень СУБД. В среде 1С:Предприятие каждый справочник представляет собой отдельную таблицу. Например, в файловой версии 1С 7.7 (DBF) справочник «А» хранится в файле вида SC*.dbf, а подчиненный справочник «Б» — в другом файле. В SQL-версиях это будут две отдельные таблицы базы данных.

В таблице подчиненного справочника «Б» для каждой строки существует специальное служебное поле Владелец (в базе данных оно хранит уникальный внутренний идентификатор (ID) элемента-владельца из справочника «А»).

Когда мы выполняем программный код непосредственного удаления:


спрА = СоздатьОбъект("Справочник.А");
спрА.НайтиПоКоду(123);
спрА.Удалить(1);

Платформа выполняет прямую команду удаления записи из таблицы справочника «А». При этом:

  1. С подчиненным справочником «Б» физически ничего не происходит. Все его записи остаются на месте в неизменном виде.
  2. Возникает нарушение ссылочной целостности. Поле Владелец в подчиненных элементах по-прежнему содержит ID удаленного элемента «А», но в таблице «А» такой записи больше нет. Ссылка становится «битой» (неразрешенной).
  3. Отображение в интерфейсе: Когда пользователь попытается открыть подчиненный элемент или вывести его в отчет, платформа попытается найти владельца по сохраненному ID. Не найдя его, 1С выведет стандартную заглушку: <Объект не найден> (ID объекта).

Различие между интерактивным и программным удалением

Давайте проанализировать ситуацию, почему поведение системы отличается в зависимости от способа удаления. Разработчики платформы заложили различную логику для действий пользователя в интерфейсе и для действий программиста в коде:

Как правильно реализовать каскадное удаление программно?

Чтобы избежать появления в информационной базе «мусора» и неразрешенных ссылок, разработчик обязан самостоятельно позаботиться об очистке подчиненных данных перед удалением владельца.

Рассмотрим подробнее правильный алгоритм непосредственного удаления элементов в 1С 7.7:

  1. Создать объект подчиненного справочника «Б».
  2. Установить фильтр по владельцу с помощью метода ИспользоватьВладельца().
  3. Выбрать подчиненные элементы и в цикле физически удалить их.
  4. Только после этого удалить сам элемент справочника «А».

Посмотрим на пример реализации этого алгоритма в коде:


спрА = СоздатьОбъект("Справочник.А");
спрБ = СоздатьОбъект("Справочник.Б");

Если спрА.НайтиПоКоду(123) = 1 Тогда
    // Шаг 1. Позиционируемся на подчиненных элементах конкретного владельца
    спрБ.ИспользоватьВладельца(спрА.ТекущийЭлемент());
    спрБ.ВыбратьЭлементы();
    
    // Шаг 2. Удаляем все подчиненные элементы в цикле
    Пока спрБ.ПолучитьЭлемент() = 1 Цикл
        спрБ.Удалить(1); // Параметр 1 означает непосредственное удаление
    КонецЦикла;
    
    // Шаг 3. Теперь, когда подчиненные элементы удалены, удаляем самого владельца
    спрА.Удалить(1);
КонецЕсли;

Важное замечание по оптимизации: Если подчиненных элементов очень много или удаление происходит в высоконагруженной базе данных, удаление каждого элемента по одному в цикле может работать медленно. В таких случаях рекомендуется оборачивать процесс в транзакцию с помощью операторов НачатьТранзакцию() и ЗафиксироватьТранзакцию().

Что делать, если «битые ссылки» уже появились в базе данных?

Если из-за ошибок в коде сторонних обработок или некорректных обменов данными в вашей базе уже образовались «сироты» без владельцев, их необходимо выявить и устранить. Для этого в платформе 1С предусмотрен штатный механизм — Тестирование и исправление информационной базы (ТИИ), доступный в режиме Конфигуратора.

Разберем по шагам, как настроить ТИИ для решения этой проблемы:

  1. Запустите Конфигуратор и обязательно сделайте резервную копию базы данных.
  2. Откройте меню «Администрирование» — «Тестирование и исправление...».
  3. Установите флажок напротив пункта «Проверка ссылочной целостности информационной базы».
  4. В группе переключателей «При наличии неразрешенных ссылок» выберите один из вариантов решения:
    • Очищать ссылки: Поле Владелец у подчиненных объектов будет очищено. Для подчиненных справочников этот вариант малопригоден, так как они не могут полноценно существовать без владельца.
    • Создавать объекты: Платформа автоматически создаст новые «пустые» элементы в справочнике-владельце «А» с наименованием вроде <Объект не найден>.... После этого вы сможете вручную перепривязать или корректно удалить эти объекты.
    • Удалять объекты: Система физически удалит все элементы справочника «Б», у которых удален владелец. Это наиболее автоматизированный способ избавления от «мусора».
  5. Нажмите кнопку «Выполнить» для запуска процесса.

Эволюция механизмов удаления в платформе 1С:Предприятие 8

Проанализируем, как изменилось поведение платформы при переходе на современные версии 1С 8. Общие принципы СУБД остались прежними, однако разработчики получили более удобные инструменты автоматизации контроля:

Таким образом, золотое правило разработчика 1С при работе с удалением данных звучит так: никогда не удаляйте объекты непосредственно через код без предварительной проверки и удаления связанных с ними подчиненных данных. Используйте для этого штатные механизмы пометки на удаление и последующее интерактивное удаление помеченных объектов, либо тщательно пишите код каскадной очистки таблиц.

← На главную