Как удалить документы и их движения в 1С 8.3 через MS SQL запрос

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

При работе с высоконагруженными базами данных 1С 8.3 стандартные механизмы удаления объектов (через встроенный язык и метод Удалить()) могут работать крайне медленно, особенно когда речь идет о свертке базы за несколько лет (поможет ускоренная свертка документов 1С через прямые SQL-запросы). В таких случаях администраторы и разработчики прибегают к прямому удалению данных средствами СУБД MS SQL Server. Однако архитектура 1С 8.3 значительно сложнее старых версий (7.7 или 8.1), и простое удаление строк может привести к фатальному повреждению логической целостности базы.

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

Шаг 1. Анализ структуры хранения данных в 1С 8.3

Прежде чем приступать к выполнению деструктивных запросов, нам необходимо понять, как 1С преобразует свои объекты метаданных в таблицы SQL (поможет инструмент анализа физической структуры базы 1С). В отличие от версии 7.7, где имена таблиц были фиксированными (например, _1SJOURN), в 1С 8.3 имена генерируются динамически (например, _Document125, _AccumReg150).

Для определения соответствия между именами в конфигураторе и именами в SQL проанализируем метод ПолучитьСтруктуруХраненияБазыДанных(). Этот метод позволяет получить таблицу, где указаны имена всех физических таблиц и их полей. Основные правила связи, которые нам пригодятся:

  1. Идентификаторы (GUID): В SQL они хранятся в поле _IDRRef (для документов) и имеют тип binary(16).
  2. Связь с движениями: Все таблицы регистров (накопления, сведений, бухгалтерии), которые были изменены документом, содержат поле _RecorderRRef. Именно по этому полю происходит связь регистра с регистратором.
  3. Журналы документов: Данные о документах также дублируются в таблицах журналов (_DocumentJournal...). Если их не очистить, в интерфейсе 1С останутся "битые" ссылки (фантомные записи).

Шаг 2. Учет смещения дат (Year Offset)

Проанализируем важную техническую особенность 1С: хранение дат. При создании базы в 1С часто выбирается опция "Смещение дат - 2000". Это делается для того, чтобы избежать проблем с минимальными значениями дат в SQL Server.

Если смещение установлено, то дата 01.01.2022 в таблицах SQL будет выглядеть как 4022-01-01. Чтобы проверить текущее смещение в вашей базе, выполним следующий запрос:


SELECT [_YearOffset] FROM [_YearOffset]

При написании запросов на удаление по периоду мы должны обязательно прибавлять это смещение к искомой дате, иначе SQL-запрос отработает впустую, не найдя ни одной записи.

Шаг 3. Динамический поиск всех таблиц движений

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

В 1С 8.3 поле, указывающее на документ-основание в регистрах, всегда называется _RecorderRRef. Мы можем составить список всех таблиц базы данных, в которых есть эта колонка:


SELECT t.name 
FROM sys.columns c 
JOIN sys.tables t ON c.object_id = t.object_id 
WHERE c.name = '_RecorderRRef'

Это позволит нам построить универсальный цикл (курсор) для очистки всех движений, связанных с удаляемыми документами.

Шаг 4. Реализация универсального скрипта удаления

Разберем по шагам логику безопасного (насколько это возможно для SQL) удаления. Предположим, мы хотим удалить документы из таблицы _Document100 (имя таблицы нужно предварительно узнать через ПолучитьСтруктуруХраненияБазыДанных), период которых меньше 1 января 2022 года.

Важно: Все операции обязательно проводим внутри транзакции!


-- 1. Создаем временную таблицу с идентификаторами удаляемых документов
SELECT _IDRRef INTO #DocsToDelete
FROM _Document100
WHERE _Date_Time < '4022-01-01 00:00:00' -- Учитываем смещение +2000 лет

-- 2. Удаляем движения из всех регистров, где эти документы являются регистраторами
DECLARE @TableName NVARCHAR(128)
DECLARE @SQL NVARCHAR(MAX)

DECLARE TableCursor CURSOR FOR
SELECT t.name 
FROM sys.columns c 
JOIN sys.tables t ON c.object_id = t.object_id 
WHERE c.name = '_RecorderRRef'

OPEN TableCursor
FETCH NEXT FROM TableCursor INTO @TableName
WHILE @@FETCH_STATUS = 0
BEGIN
    SET @SQL = 'DELETE FROM ' + QUOTENAME(@TableName) + ' WHERE _RecorderRRef IN (SELECT _IDRRef FROM #DocsToDelete)'
    EXEC sp_executesql @SQL
    FETCH NEXT FROM TableCursor INTO @TableName
END
CLOSE TableCursor
DEALLOCATE TableCursor

-- 3. Удаляем сами записи документов
DELETE FROM _Document100 WHERE _IDRRef IN (SELECT _IDRRef FROM #DocsToDelete)

-- 4. Очищаем временную таблицу
DROP TABLE #DocsToDelete

Шаг 5. Проблема журналов и регистрации изменений

Проанализируем ситуацию глубже. В 1С 8.3 документы регистрируются в журналах. Если вы удалили запись из _Document100, но не удалили её из _DocumentJournal..., пользователь все равно увидит строку в общем списке документов, но при попытке открытия получит ошибку "Объект не найден".

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

Шаг 6. Последовательность действий после удаления

После прямого выполнения DELETE в SQL база данных не уменьшится в размере автоматически, а логическая целостность итогов будет нарушена. Рассмотрим обязательные шаги по завершении процедуры:

  1. Пересчет итогов: Это самый важный этап. SQL-запрос удалил записи в таблицах движений, но не обновил агрегированные данные в таблицах итогов (например, _AccumRegTotals...). Необходимо зайти в Конфигуратор и запустить "Тестирование и исправление" с галочкой "Пересчет итогов" или воспользоваться консолью управления итогами в режиме "Предприятие".
  2. Сжатие базы данных (Shrink): SQL Server помечает место как свободное, но не отдает его операционной системе. Для освобождения дискового пространства выполните команду SHRINKDATABASE или SHRINKFILE через SQL Management Studio — для этого подойдёт универсальный инструмент для свертки и сжатия баз 1С.
  3. Обновление статистик: После массового удаления индексы могут стать неэффективными. Выполните EXEC sp_updatestats.

Критическое предупреждение

Прямое удаление данных через MS SQL — это крайняя мера. Помните о следующих рисках:

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

← На главную