При переходе с старых редакций конфигураций (например, Бухгалтерия Предприятия 2.0) на новые (редакция 3.0) администраторы и программисты часто сталкиваются с ошибками реструктуризации базы данных. Одной из самых распространенных и неприятных является ошибка: "Записи регистра сведений стали неуникальными". Чаще всего она возникает на регистрах, которые в новой редакции помечены префиксом "Удалить" (например, УдалитьКонтактнаяИнформация, УдалитьСтраховыеВзносыСкидкиКДоходам).
В этой статье мы подробно разберем причины возникновения этой ошибки, выясним, почему стандартные проверки могут не показывать дубли, и рассмотрим несколько надежных способов решения проблемы, позволяющих как просто обойти ошибку, так и сохранить важные данные.
Давайте разберемся, что происходит в момент обновления. Платформа пытается изменить структуру регистра сведений. В редакции 3.0 многие данные (например, контактная информация) переносятся из регистров сведений в табличные части справочников. Старые регистры переименовываются (добавляется префикс "Удалить") и остаются в системе временно для корректного переноса данных обработчиками обновления.
Ошибка уникальности возникает по следующим причинам:
Объект + Вид + Тип). В целевой конфигурации (3.0) регистр УдалитьКонтактнаяИнформация может иметь более строгий ключ уникальности (например, только Объект + Вид). Если в базе есть записи, различающиеся только полем Тип, для новой структуры они станут полными дублями.ВидыКонтактнойИнформации возникают дубли предопределенных элементов, созданные пользователями. При обновлении платформа пытается "свернуть" их, что приводит к появлению дублей записей в регистре.NULL, которое 1С обрабатывает специфически. При реструктуризации таблицы это может вызвать конфликт.Автор темы столкнулся с тем, что его скрипт поиска дублей не находил проблем в текущей базе. Давайте посмотрим на код, который использовался, и поймем его ошибку.
// Пример кода автора, который НЕ нашел дубли
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| КонтактнаяИнформация.Объект,
| КонтактнаяИнформация.Вид
|ИЗ
| РегистрСведений.КонтактнаяИнформация КАК КонтактнаяИнформация";
// Далее шел перебор и поиск строк в ТЗ
Почему этот код неэффективен? Он ищет дубли, исходя из текущей структуры данных. Но ошибка возникает при попытке записать эти данные в новую структуру. Чтобы найти реальные дубли, нужно моделировать ограничения уникальности именно целевой конфигурации.
Если мы хотим гарантированно сохранить данные (адреса, телефоны контрагентов и сотрудников) и при этом успешно обновиться, лучшим решением будет временное изъятие данных из "проблемного" регистра. Этот метод предложили опытные участники обсуждения.
Рассмотрим алгоритм действий по шагам:
ВыгрузкаЗагрузкаДанныхXML (она есть на ИТС или в составе конвертации данных).КонтактнаяИнформация).Теперь, когда копия данных у нас есть, мы можем очистить регистр, чтобы он не мешал обновлению. Это можно сделать с помощью обработки "Корректировка записей регистров" или простым кодом:
Набор = РегистрыСведений.КонтактнаяИнформация.СоздатьНаборЗаписей();
Набор.Записать(); // Записываем пустой набор, удаляя все записи
Запускаем обновление в Конфигураторе. Так как регистр пуст, ошибка уникальности не возникнет. Доходим до этапа принятия изменений.
Здесь есть нюанс. После обновления конфигурации, но ДО запуска в режиме "Предприятие" (где отрабатывают обработчики переноса данных), нам нужно вернуть данные.
Для этого можно воспользоваться приемом "заглушки". В модуле обычного приложения (или в общем модуле, отвечающем за обновление, например ОбновлениеИнформационнойБазы) можно временно поставить Возврат в начале процедуры обновления, чтобы база открылась, но обработчики не запустились.
Либо, как предложил автор темы, использовать встроенную обработку загрузки:
ВыгрузкаЗагрузкаДанныхXML.УдалитьКонтактнаяИнформация, так как имя в файле и в базе будет сопоставлено).После загрузки данных убираем "заглушки" и перезапускаем 1С в обычном режиме. Отработают регламентные процедуры перехода на 3.0 (например, ПереносКИПриОбновленииС20), которые корректно разнесут данные из регистра УдалитьКонтактнаяИнформация по табличным частям справочников.
Существует более изящный метод, который помогает избежать конфликтов сопоставления объектов метаданных. Он основан на том, чтобы явно указать платформе, что наш старый регистр — это и есть тот самый "удаляемый" регистр в новой конфигурации.
Рассмотрим последовательность действий:
КонтактнаяИнформация.УдалитьКонтактнаяИнформация (точно так, как он называется в новой конфигурации 3.0).ВидыКонтактнойИнформации переименовываем в УдалитьВидыКонтактнойИнформации.Почему это работает? При обновлении платформа сопоставляет объекты по внутренним идентификаторам (UUID) и именам. Если имена совпадают, система понимает: "Ага, этот объект не меняется кардинально, мы просто накатываем структуру". Это часто позволяет избежать жесткой конвертации данных, которая вызывает ошибку уникальности.
Если вы уверены, что данные в конкретном регистре являются "мусором" или служебной информацией, которую можно пересчитать (например, СтраховыеВзносыСкидкиКДоходам, которые актуализируются при расчетах, но не КонтактнаяИнформация!), можно просто удалить содержимое регистра.
Если регистр уже переименован в Удалить... и обновление зависло на этом этапе, удалить данные стандартными средствами 1С может быть невозможно (так как база не запускается). В этом случае поможет прямой SQL-запрос (только для клиент-серверных баз и опытных администраторов):
TRUNCATE TABLE _InfoRegXXXXX
-- Где _InfoRegXXXXX - имя таблицы соответствующего регистра в базе данных SQL
Важно: Всегда делайте резервную копию перед выполнением SQL-команд. Для файловой базы данный метод неприменим, там можно использовать редакторы dbf/cd (инструменты разработчика), но это рискованно.
Если вы хотите найти и устранить причину (конкретные дублирующиеся записи), а не просто обойти проблему, используйте следующий подход:
1. Правильный поиск дублей.
Ищите записи, у которых совпадают ключевые измерения целевой структуры. Для регистра контактной информации чаще всего это пара Объект и Вид. Игнорируйте измерения, которые удаляются в новой версии.
ВЫБРАТЬ
КИ.Объект,
КИ.Вид,
КОЛИЧЕСТВО(*) КАК КоличествоДублей
ИЗ
РегистрСведений.КонтактнаяИнформация КАК КИ
СГРУППИРОВАТЬ ПО
КИ.Объект,
КИ.Вид
ИМЕЮЩИЕ
КОЛИЧЕСТВО(*) > 1
2. Проверка через "Тестирование и исправление".
Перед обновлением обязательно выполняйте "Тестирование и исправление" (ТИИ) в конфигураторе с галочками "Проверка логической целостности" и "Реструктуризация таблиц". Часто это помогает выявить скрытые проблемы до начала основного процесса обновления.
3. Проверка предопределенных элементов.
Проверьте справочник ВидыКонтактнойИнформации. Если у вас есть два элемента с похожим названием (например, "Телефон рабочий" предопределенный и "Телефон рабочий" созданный пользователем), замените ссылки на созданный элемент ссылками на предопределенный и удалите дубль. Это предотвратит "схлопывание" записей при обновлении.
Ошибка уникальности записей при обновлении — это сигнал о том, что данные в старой базе не соответствуют более строгим требованиям новой структуры. Самым безопасным методом решения является выгрузка данных в XML, очистка регистра и последующая загрузка после обновления конфигурации. Это гарантирует, что важная информация (контакты клиентов, сотрудников) не будет потеряна в процессе перехода на редакцию 3.0.