При работе с платформой 1С:Предприятие 7.7 на базе MS SQL Server разработчики иногда сталкиваются с критической ошибкой: Violation of PRIMARY KEY constraint... Cannot insert duplicate key in object.... Особенно часто это происходит после внесения изменений в структуру метаданных, например, при удалении измерений из регистров. Рассмотрим подробно, почему возникает эта проблема, как проанализировать состояние базы данных и какими способами можно восстановить работоспособность системы.
Для начала разберем внутреннее устройство хранения данных в 1С 7.7. Каждый регистр в SQL-версии представлен как минимум двумя таблицами:
IDDOC и номера строки LINENO.Проанализируем ситуацию: предположим, у вас были измерения «Склад», «Товар» и «Партия». Две записи с одинаковыми складами и товарами, но разными партиями, были уникальными для SQL. После того как вы удалили измерение «Партия», эти записи с точки зрения нового состава первичного ключа стали идентичными. При попытке записать такие итоги SQL Server выдает ошибку PRIMARY KEY violation, так как он не может хранить две одинаковые строки в таблице, где задано требование уникальности.
Первым делом необходимо воспользоваться встроенными средствами конфигуратора. Процедура «Тестирование и исправление» (ТиИ) позволяет пересчитать итоги и обновить индексы таблиц. Выполним следующие действия:
1cv7.md.Во время этого процесса 1С попытается переформировать таблицу RG (итогов) на основании данных из таблицы RA (движений). Если в процессе пересчета возникнет ошибка, значит, в базе уже физически существуют дубли, которые система не может «схлопнуть» самостоятельно.
Иногда стандартное сохранение конфигурации не вызывает полной перестройки индексов SQL. Проанализируем способ «подталкивания» системы к глубокой реструктуризации:
Этот метод часто помогает, если ошибка вызвана тем, что старый индекс в SQL не удалился корректно или в файле 1cv7.dds (описание структуры базы) возникли несоответствия.
Если ошибка возникает «время от времени» при проведении конкретных документов, нам нужно выяснить, какие именно данные конфликтуют. Для этого определим имя таблицы итогов в файле 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 — это внутренние идентификаторы ваших оставшихся измерений. Если запрос вернул строки — вы нашли «виновников». Это записи, которые из-за удаления измерений стали одинаковыми в рамках одного периода.
Если тестирование и исправление не помогают, а дублей слишком много, разберем метод полной очистки итогов. Внимание: этот метод требует обязательного последующего пересчета итогов в конфигураторе!
RG123).TRUNCATE TABLE RG123;
При пересчете 1С заново прочитает все движения из таблицы RA и сформирует правильные, уникальные записи в таблице RG с учетом нового состава измерений.
Не лишним будет убедиться, что на уровне самой СУБД нет ошибок размещения данных. Проанализируем состояние базы с помощью команды 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 и повторного пересчета из Конфигуратора.