Как исправить ошибку нарушения ограничения PRIMARY KEY в 1С 7.7 после удаления измерений регистра

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

При работе с платформой 1С:Предприятие 7.7 на базе MS SQL Server разработчики иногда сталкиваются с критической ошибкой: Violation of PRIMARY KEY constraint... Cannot insert duplicate key in object.... Особенно часто это происходит после внесения изменений в структуру метаданных, например, при удалении измерений из регистров. Рассмотрим подробно, почему возникает эта проблема, как проанализировать состояние базы данных и какими способами можно восстановить работоспособность системы.

Почему возникает нарушение уникальности первичного ключа?

Для начала разберем внутреннее устройство хранения данных в 1С 7.7. Каждый регистр в SQL-версии представлен как минимум двумя таблицами:

  1. RAxxxx (таблица движений) — здесь хранятся записи, создаваемые документами. Первичный ключ обычно строится на комбинации идентификатора документа IDDOC и номера строки LINENO.
  2. RGxxxx (таблица итогов) — здесь хранятся рассчитанные остатки на начало каждого месяца. Первичный ключ в этой таблице состоит из периода (начала месяца) и набора всех измерений регистра.

Проанализируем ситуацию: предположим, у вас были измерения «Склад», «Товар» и «Партия». Две записи с одинаковыми складами и товарами, но разными партиями, были уникальными для SQL. После того как вы удалили измерение «Партия», эти записи с точки зрения нового состава первичного ключа стали идентичными. При попытке записать такие итоги SQL Server выдает ошибку PRIMARY KEY violation, так как он не может хранить две одинаковые строки в таблице, где задано требование уникальности.

Шаг 1: Полное тестирование и исправление (ТиИ)

Первым делом необходимо воспользоваться встроенными средствами конфигуратора. Процедура «Тестирование и исправление» (ТиИ) позволяет пересчитать итоги и обновить индексы таблиц. Выполним следующие действия:

  1. Создадим полную резервную копию базы данных SQL и файла 1cv7.md.
  2. Зайдем в Конфигуратор в монопольном режиме.
  3. Выберем пункт меню «Администрирование» — «Тестирование и исправление итогов».
  4. Установим все флажки, включая «Пересчет итогов», «Проверка логической целостности» и «Проверка ссылочной целостности».

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

Шаг 2: Принудительная реструктуризация таблиц

Иногда стандартное сохранение конфигурации не вызывает полной перестройки индексов SQL. Проанализируем способ «подталкивания» системы к глубокой реструктуризации:

  1. В дереве метаданных найдем проблемный регистр.
  2. Попробуем немного изменить порядок измерений (подвигать их вверх-вниз с помощью синих стрелок).
  3. Сохраним конфигурацию. Это заставит 1С пересоздать SQL-индексы для этого объекта.
  4. Вернем измерения в нужный порядок и снова сохранимся.

Этот метод часто помогает, если ошибка вызвана тем, что старый индекс в SQL не удалился корректно или в файле 1cv7.dds (описание структуры базы) возникли несоответствия.

Шаг 3: Поиск дублей с помощью SQL-запроса

Если ошибка возникает «время от времени» при проведении конкретных документов, нам нужно выяснить, какие именно данные конфликтуют. Для этого определим имя таблицы итогов в файле 1cv7.dds (например, RG123) и выполним запрос в SQL Server Management Studio. Рассмотрим пример запроса для поиска дублирующихся ключей:


SELECT PERIOD, SP100, SP101, COUNT(*)
FROM RG123 (NOLOCK)
GROUP BY PERIOD, SP100, SP101
HAVING COUNT(*) > 1

В данном примере SP100 и SP101 — это внутренние идентификаторы ваших оставшихся измерений. Если запрос вернул строки — вы нашли «виновников». Это записи, которые из-за удаления измерений стали одинаковыми в рамках одного периода.

Шаг 4: Радикальное решение через очистку таблицы итогов

Если тестирование и исправление не помогают, а дублей слишком много, разберем метод полной очистки итогов. Внимание: этот метод требует обязательного последующего пересчета итогов в конфигураторе!

  1. Выясняем имя таблицы итогов для регистра (например, RG123).
  2. В SQL Management Studio выполняем команду: TRUNCATE TABLE RG123;
  3. После этого таблица итогов станет пустой. Теперь заходим в Конфигуратор и запускаем «Управление итогов» — «Установить расчет по...» (выбираем текущий месяц) и выполняем полный пересчет.

При пересчете 1С заново прочитает все движения из таблицы RA и сформирует правильные, уникальные записи в таблице RG с учетом нового состава измерений.

Шаг 5: Проверка целостности на уровне SQL

Не лишним будет убедиться, что на уровне самой СУБД нет ошибок размещения данных. Проанализируем состояние базы с помощью команды DBCC CHECKDB. Это исключит вероятность того, что ошибка вызвана повреждением страниц данных на диске:


-- Выполнить в Query Analyzer или SSMS
DBCC CHECKDB ('Имя_Вашей_Базы') WITH NO_INFOMSGS, ALL_ERRORMSGS;

Если команда возвращает ошибки размещения (allocation errors) или согласованности (consistency errors), проблему нужно решать средствами восстановления SQL Server, а не только инструментами 1С.

Выясним причину появления «нулевых» записей

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

Важное резюме: при удалении измерений в 1С 7.7 всегда делайте это сначала на копии, после чего обязательно проводите полный цикл тестирования и исправления итогов. Если ошибка PRIMARY KEY перекочевала в рабочую базу, используйте комбинацию из очистки таблицы итогов через TRUNCATE и повторного пересчета из Конфигуратора.

← На главную