Как выполнить программное непосредственное удаление объектов в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В практике разработки на платформе 1С нередко возникают задачи технической очистки информационных баз — например, при подготовки рабочей копии для аудита, подготовке базы к сжатию или подготовке демонстрационного стенда. В отличие от стандартного пометки на удаление с последующим контролем ссылочной целостности, непосредственное удаление стирает элементы из базы данных напрямую.

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

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

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

  1. Образование битых ссылок: если удаляемый элемент справочника (например, контрагент или номенклатура) фигурирует в оставшихся документах или регистрах, на его месте появится запись вида <Объект не найден...>.
  2. Потеря подчиненных данных: при удалении основных элементов подчиненные справочники (единицы измерения, контактная информация, банковские счета) не удаляются автоматически и остаются "мусором" в базе.
  3. Повреждение регистров учета: при удалении проведенных документов без предварительной очистки их движений в регистрах накопления и сведений остаются записи без регистратора.

Обязательное условие: все операции непосредственного удаления необходимо выполнять строго на резервной копии информационной базы.

Способ 1. Удаление через обход метаданных и метод Объект.Удалить()

Разберем классический подход с использованием встроенного языка. Метод Удалить() вызывается у объекта информационной базы и полностью удаляет запись из базы данных. При этом вызове отрабатывают стандартные события модуля объекта (ПередУдалением, ПриУдалении) и подписки на события.

Посмотрим на пример обхода метаданных для удаления документов и справочников:


Запрос = Новый Запрос;

Менеджеры = Новый СписокЗначений;
Менеджеры.Добавить("Документы", "Документ");
Менеджеры.Добавить("Справочники", "Справочник");

Для Каждого Элемент Из Менеджеры Цикл
    ВЗапрос = Элемент.Представление;
    ТипОбъекта = Метаданные[Элемент.Значение];
    
    Для Каждого Вид Из ТипОбъекта Цикл
        ИмяОбъекта = Вид.Имя;
        Запрос.Текст = "ВЫБРАТЬ Нечто.Ссылка КАК Ссылка ИЗ " + ВЗапрос + "." + ИмяОбъекта + " КАК Нечто";
        Выборка = Запрос.Выполнить().Выбрать();
        
        Пока Выборка.Следующий() Цикл
            ОбъектДляУдаления = Выборка.Ссылка.ПолучитьОбъект();
            Если ОбъектДляУдаления <> Неопределено Тогда
                ОбъектДляУдаления.Удалить();
            КонецЕсли;
        КонецЦикла;    
    КонецЦикла;    
КонецЦикла;

Способ 2. Массовое прямое удаление процедурой УдалитьОбъекты()

Платформа 1С предоставляет глобальную процедуру УдалитьОбъекты(). В отличие от метода Удалить() у конкретного объекта, функция УдалитьОбъекты(МассивСсылок, Ложь) удаляет массив элементов напрямую из таблиц СУБД, минуя обработчики модуля объекта. Это существенно ускоряет процесс обработка больших объемов данных.

Проанализируем пример массового удаления документов с фильтрацией по организации:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	АвансовыйОтчет.Ссылка КАК Ссылка
    |ИЗ
    |	Документ.АвансовыйОтчет КАК АвансовыйОтчет
    |ГДЕ
    |	АвансовыйОтчет.Организация = &Организация";

Запрос.УстановитьПараметр("Организация", ВыбраннаяОрганизация);
Результат = Запрос.Выполнить().Выгрузить();

МассивУдаления = Результат.ВыгрузитьКолонку("Ссылка");

// Второй параметр Ложь означает отключение проверки ссылочной целостности
УдалитьОбъекты(МассивУдаления, Ложь);

Очистка движений документов перед удалением

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

Рассмотрим два варианта очистки движений:

Вариант A. Очистка через коллекции движений объекта


Для Каждого Движение Из ДокументОбъект.Движения Цикл
    Движение.Прочитать();
    Движение.Очистить();
КонецЦикла; 
ДокументОбъект.Записать();
ДокументОбъект.Удалить();

Вариант B. Быстрая очистка через набор записей регистра (оптимально для больших объемов)

Для предотвращения избыточной нагрузки на оперативную память при вызове Прочитать() эффективнее записывать пустой набор записей с отбором по регистратору:


Набор = РегистрыНакопления.Продажи.СоздатьНаборЗаписей();
Набор.Отбор.Регистратор.Установить(СсылкаНаДокумент);
Набор.Записать(); // Запись пустого набора удаляет записи регистратора

Рекомендации по оптимизации и завершению очистки

Для корректного и быстрого завершения процедуры удаления рекомендуем соблюдать следующие правила:

  1. Отключение пересчета итогов: при массовом удалении проведенных документов отключите авторасчет итогов регистров накопления с помощью вызова РегистрыНакопления[ИмяРегистра].УстановитьИспользованиеИтогов(Ложь) и включите его после завершения обработки.
  2. Порционная обработка: при удалении сотен тысяч записей оборачивайте операции в транзакции небольшими порциями (по 500–1000 элементов) с помощью НачатьТранзакцию() и ЗафиксироватьТранзакцию(), чтобы избежать переполнения журнала транзакций СУБД.
  3. Устранение битых ссылок: по окончании процесса откройте Конфигуратор и запустите утилиту Тестирование и исправление информационной базы. Отметьте пункт «Проверка логической целостности» и выберите вариант «Очищать ссылки» при обнаружении несуществующих объектов.
  4. Освобождение дискового пространства: прямое удаление записей не уменьшает размер файла базы данных автоматически. В файловом режиме (.1CD) выполните процедуру «Сжатие таблиц информационной базы» или запустите chdbfl.exe. В клиент-серверном режиме запустите регламентную процедуру сжатия базы (Shrink) на стороне MS SQL Server или команду VACUUM FULL в PostgreSQL.
← На главную