Как исправить ошибку неуникальности записей при загрузке базы 1С из DT в MS SQL Server?

Программист 1С v8.3 (Обычные формы) 1С:Комплексная автоматизация Бухгалтерский учет IT и автоматизация бизнеса
← На главную

При переносе информационной базы 1С из файлового режима (файл .1CD) в клиент-серверный вариант под управлением Microsoft SQL Server через стандартную выгрузку и загрузку файла .dt нередко возникает критическая ошибка: «Попытка вставки неуникального значения в уникальный индекс» (The CREATE UNIQUE INDEX statement terminated because a duplicate key was found). Чаще всего сбой происходит на таблицах итогов (_AccRgT) или таблицах значений субконто регистра бухгалтерии (_AccRgED).

Разберем природу этой проблемы, выясним, почему файловая база работает без видимых сбоев, и подробно рассмотрим пошаговые методы устранения дублирующихся записей.

Почему ошибка проявляется именно при переходе на SQL Server?

В файловой СУБД 1С контроль уникальности вторичных таблиц и индексов устроен менее строго, чем в реляционных промышленных СУБД. При аварийных завершениях сеансов, сетевых сбоях или работе с базами критического объема (свыше 10–15 ГБ) во внутренних таблицах могут оставаться скрытые дубли строк или фантомные записи от прерванных транзакций.

Механизм создания выгрузки .dt выполняет последовательную логическую сериализацию данных, не производя жесткой проверки уникальности записей. При последующей загрузке в MS SQL Server платформа сначала вставляет строки в созданные таблицы, а затем формирует уникальные индексы. Если в данных обнаруживаются одинаковые сочетания ключевых полей, SQL Server аварийно прерывает операцию с ошибкой создания индекса.

Анализ типа сбойной таблицы

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

  1. Таблица итогов регистра бухгалтерии (_AccRgT<n>): сбой возникает из-за расхождения и дублирования рассчитанных итогов. Быстрое решение для обхода этой ошибки перед выгрузкой — отключить итоги в исходной базе. Для этого в режиме «1С:Предприятие» через обработку «Управление итогами» необходимо отключить итоги по всем регистрам, выполнить выгрузку, загрузить базу в SQL Server и включить итоги заново с пересчетом.
  2. Таблица субконто регистра бухгалтерии (_AccRgED<n>): создается для регистров бухгалтерии, поддерживающих субконто. В ней хранятся аналитические разрезы проводок. Отключение итогов на эту таблицу не влияет, так как она хранит детальные движения. Здесь требуется найти конкретные сбойные проводки и удалить дубли.

Способ 1. Поиск и исправление проблемы в файловой базе

Если процесс загрузки базы на SQL прервался, наиболее надежным путем является устранение повреждений в исходной файловой базе перед созданием повторного архива .dt.

Разберем по шагам, как выявить и очистить поврежденные данные:

  1. Локализация сбойного документа: в тексте ошибки приводится шестнадцатеричный идентификатор регистратора (поле _RecorderRRef). В большинстве случаев дублирование движений субконто порождают тяжелые регламентные документы, такие как Расчет себестоимости, проводящиеся с огромным количеством проводок.
  2. Проверка утилитой тестирования: перед штатными процедурами обязательно закроем все сеансы и выполним проверку файла базы утилитой chdbfl.exe (находится в каталоге bin платформы 1С) с активным флагом «Исправлять обнаруженные ошибки». Это восстановит целостность файловых страниц.
  3. Программная очистка движений проблемного документа: если при попытке интерактивной отмены проведения документа возникает ошибка неуникальности, очистим набор записей регистра программно с помощью короткого скрипта:
    
    ПроблемнаяСсылка = Документы.РасчетСебестоимостиВыпуска.НайтиПоНомеру("000000012", Дата("20141130"));
    
    Набор = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
    Набор.Отбор.Регистратор.Установить(ПроблемнаяСсылка);
    Набор.Записать(); // Запись пустого набора удаляет движения и связанные субконто
    
  4. Тестирование и исправление: запустим в Конфигураторе операцию «Тестирование и исправление информационной базы». Обязательно активируем пункты «Проверка логической целостности» и «Проверка ссылочной целостности» с выбором действия «Очищать ссылки», а при наличии движений без регистратора — «Удалять движения».
  5. Повторный перенос: выгрузим базу в новый файл .dt, выполним загрузку в MS SQL Server и перепроведем очищенный документ в новой базе.

Способ 2. Устранение дублей напрямую в MS SQL Server

Поскольку физическая вставка записей в таблицы завершается до момента построения индексов, базу можно исправить непосредственно на стороне сервера СУБД, не повторяя многочасовую выгрузку и загрузку 15 ГБ данных.

Разберем по шагам процесс исправления на стороне SQL Server:

  1. Выявление дублирующихся строк: выполним запрос к таблице, указанной в ошибке (например, _AccRgED1152), с группировкой по ключевым полям индекса:
    
    SELECT [_Period]
          ,[_RecorderTRef]
          ,[_RecorderRRef]
          ,[_LineNo]
          ,[_Correspond]
          ,[_KindRRef]
          ,COUNT(*) AS [TotalDuplicates]
      FROM [dbo].[_AccRgED1152]
      GROUP BY [_Period]
              ,[_RecorderTRef]
              ,[_RecorderRRef]
              ,[_LineNo]
              ,[_Correspond]
              ,[_KindRRef]
      HAVING COUNT(*) > 1;
    
  2. Удаление лишних экземпляров записей: с помощью обобщенного табличного выражения (CTE) и функции ROW_NUMBER() удалим дублирующие строки, оставив по одной уникальной записи для каждой связки ключей:
    
    WITH DuplicatesCTE AS (
        SELECT 
            _Period, _RecorderTRef, _RecorderRRef, _LineNo, _Correspond, _KindRRef,
            ROW_NUMBER() OVER (
                PARTITION BY _Period, _RecorderTRef, _RecorderRRef, _LineNo, _Correspond, _KindRRef 
                ORDER BY (SELECT NULL)
            ) AS RowNum
        FROM [dbo].[_AccRgED1152]
    )
    DELETE FROM DuplicatesCTE WHERE RowNum > 1;
    
  3. Восстановление уникального индекса: после очистки дублей создадим индекс, выполнение которого завершилось сбоем при загрузке:
    
    CREATE UNIQUE CLUSTERED INDEX [_AccRgED1152_ByPeriod_TRNRN] 
    ON [dbo].[_AccRgED1152] (_Period, _RecorderTRef, _RecorderRRef, _LineNo, _Correspond, _KindRRef);
    

    Вместо ручного выполнения SQL-команда создания индекса можно запустить Конфигуратор 1С и выполнить «Тестирование и исправление» с установленным единственным флагом «Реструктуризация таблиц информационной базы». Платформа проверит структуру и автоматически создаст все недостающие индексы.

После завершения процедур откроем базу в режиме «1С:Предприятие», выполним проверку движений затронутого регистратора и проконтролируем корректность бухгалтерских итогов с помощью стандартных отчетов (оборотно-сальдовая ведомость).

← На главную