Как правильно и быстро удалить документы в 1С:Предприятии 7.7 через SQL или штатные средства?

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

При работе с базами данных 1С:Предприятия 7.7, особенно в случаях подготовки копий баз для филиалов или очистки старых данных, часто возникает задача массового удаления документов. Стандартные методы могут работать крайне медленно, что толкает разработчиков на использование прямых SQL-запросов. Однако прямое удаление из SQL-таблиц в 1С 7.7 таит в себе множество подводных камней, связанных с нарушением ссылочной целостности и логики учета. Рассмотрим подробно, как устроена структура хранения документов и какие методы позволяют выполнить удаление максимально эффективно и безопасно.

Структура хранения документов в SQL-версии 1С 7.7

Для того чтобы понять, почему простой запрос DELETE FROM _1SJourn не сработает, проанализируем, в каких таблицах распределены данные одного документа. В 1С 7.7 документ — это не одна запись, а целый комплекс связанных данных:

  1. _1SJourn — общий журнал документов. Здесь хранится базовая информация: дата, номер, тип документа (IDDocDef), пометка удаления, статус проведения и уникальный идентификатор IDDoc.
  2. DH[ID] (Document Header) — таблица шапки конкретного вида документа. Вместо [ID] подставляется внутренний идентификатор метаданных (например, DH123). Здесь лежат реквизиты шапки.
  3. DT[ID] (Document Table) — таблица табличной части документа. Здесь хранятся строки документа.
  4. _1SCrdoc — таблица критически важных связей. Она отвечает за критерии отбора и иерархию (подчиненные документы). Если ее не очистить, в журналах останутся «битые» ссылки.
  5. _1SOper и _1SEntry — если документ делает бухгалтерские проводки, данные записываются в таблицу операций и таблицу проводок.
  6. RA[ID] и RG[ID] — таблицы движений и итогов регистров. Проведенный документ оставляет записи в RA*, которые напрямую влияют на остатки в RG*.

Важно понимать: если вы удалите запись только из _1SJourn, данные в DH, DT и регистрах останутся «сиротами». Это приведет к катастрофическим ошибкам при пересчете итогов или попытке тестирования и исправления базы.

Метод 1: Прямое удаление через SQL (Риски и реализация)

Попытка автора темы использовать простой DELETE с соединением через JOIN в одном запросе синтаксически неверна для SQL Server в том виде, в котором она была представлена. Рассмотрим, как мог бы выглядеть алгоритм прямого удаления, если всё же принято решение идти по этому пути.

Проанализируем необходимые действия:

  1. Сначала необходимо определить список IDDoc удаляемых документов.
  2. Затем нужно динамически сформировать запросы для всех таблиц DH и DT, относящихся к удаляемым видам документов.
  3. Удалить движения из всех таблиц регистров (RA*).
  4. Очистить записи в _1SCrdoc.
  5. В последнюю очередь удалить записи из _1SJourn.

Однако, как справедливо заметили участники обсуждения, такой подход требует идеального знания структуры конкретной конфигурации. Малейшая ошибка (например, забытая таблица последовательностей _1SStx) приведет к неработоспособности базы в будущем.

Метод 2: Оптимизированный штатный метод (Рекомендуемый)

Выясним причину, почему штатное удаление ТекущийДокумент().Удалить(1) работает медленно. Основное время тратится на:

Мы можем значительно ускорить этот процесс, используя «хитрости», предложенные опытными разработчиками в теме. Разберем этот алгоритм по шагам:

Шаг 1: Отключение фиксации транзакций и журнала регистрации

Работа в транзакции позволяет SQL серверу не сбрасывать данные на диск после каждого удаленного документа, а делать это порциями. Также рекомендуется временно отключить регистрацию событий в Конфигураторе (Журнал регистрации), так как запись текстовых логов при массовых операциях создает огромную нагрузку на дисковую подсистему.

Шаг 2: Перенос точки актуальности (ТА) назад

Это самый эффективный прием для ускорения удаления проведенных документов. В 1С 7.7 при удалении проведенного документа система пытается пересчитать итоги от даты документа до ТА. Если мы установим ТА на самую раннюю возможную дату (например, на начало 1980 года), то пересчета фактически не будет, так как нет документов «после» этой точки.

Пример кода для реализации ускоренного удаления:


// 1. Устанавливаем монопольный режим для скорости
// 2. Переносим ТА в глубокое прошлое
Сервис = СоздатьОбъект("Сервис"); // Если используется компонента 1С++ или штатно через установку ТА
УстановитьТАна(НачДата); 

// 3. Начинаем транзакцию
ОчиститьДанные = СоздатьОбъект("Документ");
ВыбранныеДокументы = СоздатьОбъект("ТаблицаЗначений");
// Предположим, список IDDoc уже получен запросом или выборкой

НачатьТранзакцию();
Сч = 0;
Док.ВыбратьДокументы(ДатаНач, ДатаКон);
Пока Док.ПолучитьДокумент() = 1 Цикл
    // Проверяем условия (например, по складу)
    Если Док.Склад <> НужныйСклад Тогда
        Док.Удалить(1); // 1 - удаление без корзины (сразу)
        Сч = Сч + 1;
    КонецЕсли;
    
    // Фиксируем транзакцию каждые 1000 документов, чтобы не переполнить лог SQL
    Если Сч % 1000 = 0 Тогда
        ЗафиксироватьТранзакцию();
        НачатьТранзакцию();
    КонецЕсли;
КонецЦикла;
ЗафиксироватьТранзакцию();

Сравнение подходов

Проанализируем ситуацию: стоит ли использовать прямой SQL? Если ваша задача — удалить 90% данных из огромной базы для создания «пустышки», то штатный метод даже с переносом ТА может занять часы. В этом случае программисты иногда используют TRUNCATE TABLE для полной очистки таблиц движений и журналов, но это требует последующего восстановления структуры через «Тестирование и исправление».

Для выборочного удаления (например, по конкретному складу, как у автора темы) штатный метод Удалить(1) внутри транзакции с предварительным переносом ТА назад является золотым стандартом. Он гарантирует:

Резюме

Рассмотренная тема подтверждает: лезть «лапками» в SQL-таблицы 1С 7.7 без крайней необходимости не стоит. Использование штатных методов платформы в сочетании с инженерными приемами (управление точкой актуальности и транзакциями) позволяет добиться высокой скорости работы при сохранении полной целостности базы данных. Если же вы решите использовать SQL, помните о необходимости очистки всех связанных таблиц: от _1SJourn до _1SCrdoc и таблиц проводок.

← На главную