При обновлении конфигураций 1С на очередную версию разработчики иногда сталкиваются с ошибкой реструктуризации базы данных: «Записи регистра не уникальны». Процесс реструктуризации при этом аварийно прерывается, и платформа не позволяет завершить сохранение конфигурации базы данных. Чаще всего это происходит с непериодическими или независимыми регистрами сведений, такими как ЦеныНоменклатурыДокументов. Разберем по шагам, почему возникает эта ошибка и как восстановить работоспособность базы без безвозвратной потери накопленных данных.
Механизм реструктуризации в платформе 1С переносит существующие данные во временную таблицу новой структуры и затем создает уникальный индекс по ключевым полям (период плюс измерения). Если в исходных данных после приведения к новой структуре образуются две или более строки с одинаковым набором ключевых полей, СУБД возвращает ошибку нарушения уникальности, и транзакция отменяется.
Проанализируем основные причины, приводящие к появлению дублей:
По позиции регистратора или регистр был непериодическим, а разработчики перевели его на периодичность День или Месяц, все записи, созданные внутри одного дня, склеиваются по ключу периода.Если обновление выполнялось сразу через релиз (например, переход через 2–3 версии за один раз), наиболее правильный путь — вернуться на шаг назад:
Если обновление выполняется строго по инструкции, но ошибка все равно возникает, локализуем дублирующиеся строки запросом. Выясним, какие измерения регистра остаются в новом релизе, и выполним запрос к проблемной таблице еще до применения реструктуризации.
Посмотрим на пример запроса для поиска коллизий:
ВЫБРАТЬ
Регистр.Номенклатура КАК Номенклатура,
Регистр.Характеристика КАК Характеристика,
КОЛИЧЕСТВО(*) КАК КоличествоДублей
ИЗ
РегистрСведений.ЦеныНоменклатурыДокументов КАК Регистр
СГРУППИРОВАТЬ ПО
Регистр.Номенклатура,
Регистр.Характеристика
ИМЕЮЩИЕ
КОЛИЧЕСТВО(*) > 1
После выявления записей, которые образуют дубли, напишем простую внешнюю обработку, которая очистит дубликаты, оставив только актуальные данные. Для независимого регистра сведений удаление и перезапись осуществляются через объект РегистрСведенийНаборЗаписей:
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Набор = РегистрыСведений.ЦеныНоменклатурыДокументов.СоздатьНаборЗаписей();
Набор.Отбор.Номенклатура.Установить(Выборка.Номенклатура);
Набор.Отбор.Характеристика.Установить(Выборка.Характеристика);
// Считываем текущие дублирующиеся записи
Набор.Прочитать();
Если Набор.Количество() > 1 Тогда
// Оставляем только последнюю актуальную запись
Пока Набор.Количество() > 1 Цикл
Набор.Удалить(0);
КонецЦикла;
Набор.Записать(Истина);
КонецЕсли;
КонецЦикла;
Если записей слишком много, либо структура кардинально перерабатывается поставщиком, воспользуемся проверенным сценарием с выгрузкой данных во внешнее хранилище:
ЦеныНоменклатурыДокументов является независимым и вспомогательным (кэширующим), его очистка не нарушит целостность финансовых или складских проводок.Иногда возникает соблазн «обмануть» платформу: добавить в регистр сведений еще одно измерение с уникальным идентификатором (например, типа УникальныйИдентификатор или Число), чтобы все записи формально стали уникальными. Делать этого категорически не рекомендуется по следующим причинам:
СрезПоследних) работают в разрезе типовых измерений. При наличии дополнительного измерения платформа будет возвращать дублирующиеся строки цен, что приведет к непредсказуемым ошибкам в документах товародвижения.