При выполнении обмена данными между информационными базами через «1С:Конвертацию данных 2.1» (КД 2.1) или планы обмена может возникнуть критическая ошибка уровня СУБД Microsoft SQL Server: «Не удается вставить повторяющуюся строку ключа в объект "dbo._Reference..." с уникальным индексом "...HPK"». Ошибка сопровождается native-кодом 2601 и SQLSTATE=23000.
Разберем природу возникновения этой ошибки, выясним, почему платформа пытается выполнить вставку существующей записи вместо её обновления, и рассмотрим безопасные способы устранения конфликта.
Проанализируем структуру таблиц справочников в СУБД. Таблица справочника (например, _Reference73) имеет первичный кластерный индекс _Reference73HPK, который строится по полям _IDRRef (внутренний уникальный идентификатор GUID объекта) и признаку разделителя данных. Ошибка означает, что СУБД пытается выполнить операцию INSERT со значением _IDRRef, которое уже физически присутствует в таблице.
Такая ситуация в типовых механизмах обмена (КД 2.1) возникает по следующим причинам:
УстановитьСсылкуНового(), передавая GUID источника. Когда объект записывается, СУБД пытается выполнить INSERT с этим GUID, но в базе-приемнике запись с таким _IDRRef уже существует, что приводит к нарушению уникальности индекса._IDRRef и системным именем через поле _PredefinedID. Если в базе-источнике и базе-приемнике предопределенные элементы создавались независимо или привязывались вручную, их GUID могут различаться, что вызывает конфликт при попытке сопоставления.ИмяПредопределенныхДанных изменения фиксируются в базе данных, но серверный кэш метаданных может продолжать хранить старую структуру до перезапуска службы.Рассмотрим правильный подход к настройке правил конвертации, который исключает возникновение дублирования ключей при загрузке.
UPDATE), а не вставку нового элемента.ПоляПоиска правила конвертации:
Если СвойстваПоиска.Свойство("Наименование") И СвойстваПоиска.Наименование = "Праздники без повышенной оплаты" Тогда
СсылкаНаОбъект = Справочники.ВидыИспользованияРабочегоВремени.ПраздникиБезПовышеннойОплаты;
КонецЕсли;
Это заставит механизм обмена сопоставить входящие данные с уже существующим элементом справочника независимо от различий в GUID.
Если в базе-приемнике элемент справочника был создан пользователем вручную и не связан с метаданными конфигуратора, привяжем его программно через реквизит ИмяПредопределенныхДанных:
Процедура ПривязатьПредопределенныйЭлемент()
ЭлементСправочника = Объект.ВидыИспользованияРабочегоВремени.ПолучитьОбъект();
ЭлементСправочника.ИмяПредопределенныхДанных = "ПраздникиБезПовышеннойОплаты";
Попытка
ЭлементСправочника.Записать();
Сообщить("Элемент успешно связан с предопределенным значением метаданных.");
Исключение
Сообщить("Ошибка при записи: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Важно: После выполнения данной процедуры обязательно выполним перезапуск службы сервера «1С:Предприятия» (или рабочих процессов кластера), чтобы очистить кэш предопределенных элементов и исключить ошибки адресации в памяти сервера.
Если в базе уже присутствуют две записи (одна предопределенная, а вторая была создана обменом или вручную), не следует удалять строки прямыми запросами к СУБД. Прямой DELETE или TRUNCATE на уровне SQL оставляет битые ссылки в таблицах движений документов и регистрах сведений.
Разберем правильный порядок действий:
Если ошибки уникальности продолжают проявляться даже при корректных данных, проанализируем состояние физических индексов таблицы. В результате сбоев питания или аварийных остановок кластера индекс СУБД может быть поврежден.
Для восстановления целостности выполним перестроение индекса таблицы в среде SQL Server Management Studio (SSMS):
ALTER INDEX ALL ON dbo._Reference73 REBUILD;
После перестроения индексов рекомендуется провести штатное «Тестирование и исправление информационной базы» в конфигураторе с установленными флагами «Реиндексация таблиц информационной базы» и «Проверка логической целостности».