При обслуживании и свертке баз 1С:Предприятия 7.7 на файловой структуре (DBF) нередко возникает задача полной очистки документов с сохранением нормативно-справочной информации и отдельных видов документов (например, договоров или кадровых приказов). Простое физическое удаление файлов таблиц документов (файлов DH*.DBF и DT*.DBF) через командную строку приводит к необратимому нарушению целостности информационной базы.
Разберем архитектурные особенности хранения документов в 1С 7.7, выясним, почему нельзя просто удалить файлы с диска, и рассмотрим корректные способы решения этой задачи.
Проанализируем структуру хранения документов в платформе 1С 7.7:
IDDOCDEF и идентификатор IDDOC) регистрируются в файле 1SJOURN.DBF. Если удалить этот файл или оставить в нем записи удаленных шапок, журнал перестанет отображать документы или будет ссылаться на несуществующие строки. Штатное «Тестирование и исправление» не создает заново записи в журнале только по файлам шапок.DH<ID>.DBF, а строки табличной части — в DT<ID>.DBF, где идентификатор таблицы берется из файла структуры 1cv7.dd.1SCRDOC.DBF), периодическими реквизитами (1SCONST.DBF), бухгалтерскими операциями и проводками (1SOPER.DBF, 1SENTRY.DBF), а также регистрами (RA*, RG*).Рассмотрим вариант быстрого удаления данных на уровне базы данных с использованием компоненты прямого доступа к DBF (например, через провайдер VFPOLEDB.1 или класс OLEDBData из 1С++). Этот способ во много раз быстрее стандартного объектного удаления, так как выполняет пакетные SQL-инструкции DELETE напрямую в файлах таблиц.
Разберем по шагам логику обработки:
1SJOURN все записи, кроме нужного вида документа (в примере — «Договор»).DH*) и табличных частей (DT*) для всех остальных видов документов.1SCRDOC), периодику (1SCONST), бухгалтерские проводки (1SENTRY) и операции (1SOPER).Посмотрим на пример программного кода внешней обработки:
Процедура Сформировать()
Соединение = "Provider=VFPOLEDB.1;Data Source=" + КаталогИБ() + ";Exclusive=Yes;Mode=ReadWrite;Collating Sequence=MACHINE";
ДБ = СоздатьОбъект("OLEDBData");
Рез = ДБ.Соединение(Соединение);
Запрос = ДБ.СоздатьКоманду();
Запрос.Выполнить("EXECSCRIPT('SET ANSI OFF')");
Запрос.Выполнить("EXECSCRIPT('SET REFRESH TO 0,-1')");
Запрос.Выполнить("Exec('SET TABLEVALIDATE TO 0')");
ВидДокумента = "Договор";
// Удаляем из общего журнала все документы, кроме указанного вида
ТекстЗапроса = "
|DELETE
|FROM
| 1sjourn
|WHERE
| iddocdef+dtos(date)+time+iddoc NOT LIKE $ВидДокумента." + ВидДокумента + "+'_______________________'
|";
Запрос.ВыполнитьИнструкцию(ТекстЗапроса);
// Очищаем таблицы шапок и табличных частей остальных документов
Для к = 1 По Метаданные.Документ() Цикл
мета = Метаданные.Документ(к).Идентификатор;
Если мета = ВидДокумента Тогда
Продолжить;
КонецЕсли;
Состояние("Шапка " + мета);
ТекстЗапроса = "
|DELETE
|FROM
| $Документ." + мета + "
|";
Запрос.ВыполнитьИнструкцию(ТекстЗапроса);
Состояние("Строки " + мета);
ТекстЗапроса = "
|DELETE
|FROM
| $ДокументСтроки." + мета + "
|";
Запрос.ВыполнитьИнструкцию(ТекстЗапроса);
КонецЦикла;
// Очищаем связи подчиненных документов
Состояние("Очистка 1SCRDOC");
ТекстЗапроса = "
|DELETE
|FROM
| 1SCRDOC
|WHERE CHILDID NOT IN (SELECT Жур.iddoc FROM 1sjourn as Жур)";
Запрос.ВыполнитьИнструкцию(ТекстЗапроса);
// Очищаем периодические реквизиты, привязанные к удаленным документам
Состояние("Очистка 1SCONST");
ТекстЗапроса = "
|DELETE
|FROM
| 1SCONST
|WHERE DOCID <> ' 0 ' AND DOCID NOT IN (SELECT Жур.iddoc FROM 1sjourn as Жур)";
Запрос.ВыполнитьИнструкцию(ТекстЗапроса);
// Очищаем бухгалтерские проводки
Состояние("Очистка 1SENTRY");
ТекстЗапроса = "
|DELETE
|FROM
| 1SENTRY
|WHERE (DOCID NOT IN (SELECT Жур.iddoc FROM 1sjourn as Жур))";
Запрос.ВыполнитьИнструкцию(ТекстЗапроса);
// Очищаем бухгалтерские операции
Состояние("Очистка 1SOPER");
ТекстЗапроса = "
|DELETE
|FROM
| 1SOPER
|WHERE DOCID NOT IN (SELECT Жур.iddoc FROM 1sjourn as Жур)";
Запрос.ВыполнитьИнструкцию(ТекстЗапроса);
Предупреждение("Удаление завершено. Необходимо сжать таблицы и удалить CDX.");
КонецПроцедуры
В формате DBF инструкция DELETE лишь помечает записи на удаление (байт 0x2A). Для полного освобождения места и перестроения индексов выполним следующие шаги:
PACK) для всех измененных DBF-файлов, чтобы физически вырезать удаленные строки.*.CDX из каталога базы данных.Если нет уверенности в структуре низкоуровневых связей конфигурации, самым безопасным подходом является создание пустой копии базы с последующим переносом нужных объектов.
Разберем порядок выполнения:
1cv7.md из рабочей базы.1cv7.dd.Этот подход гарантирует отсутствие «битых» ссылок в регистрах, таблицах блокировок 1SDNLOCK и таблицах последовательностей 1SSTREAM.