Регистр сведений не обновляется: ищем и удаляем дубли записей

· 9 мин

Содержание

Вы запустили обновление конфигурации , и на этапе реструктуризации база останавливается с сообщением вроде Записи регистра сведений ... стали неуникальными. Конфигурация не применилась, пользователей в базу лучше не пускать. Причина одна: разработчик изменил состав измерений или ключевых полей регистра, а в таблице уже лежат строки, которые по новому ключу совпадают.

Лечится это в три шага: узнать, какой именно регистр и по каким полям не проходит, найти дубли запросом и убрать лишние строки. Сделать это можно в режиме Предприятия, во внешней обработке или напрямую в СУБД. Ниже все три способа, от безопасного к жёсткому.

Прежде чем что-то удалять, сделайте выгрузку информационной базы (.dt) или копию файла 1Cv8.1CD. Удаление строк регистра необратимо, а при ошибке в условии можно потерять и нужные записи.

Почему при обновлении 1С находит неуникальные записи

У регистра сведений ключ уникальности составляют измерения и, если регистр периодический, период. Платформа не позволяет записать две строки с одинаковым ключом, но только пока структура не менялась. Когда структура меняется, в таблице уже могут лежать строки, которые раньше были разными, а теперь стали одинаковыми.

Типичные сценарии:

  • 🔧 из регистра удалили измерение (например, «Организация»), и строки разных организаций слились в одну по оставшимся полям;
  • 📅 у регистра сменили периодичность: был «В пределах секунды», стал «В пределах дня», и две записи за один день теперь совпали;
  • 🔁 измерение стало ресурсом или реквизитом, ключ сузился;
  • 🧩 типовой регистр доработали в расширении или в собственной конфигурации, а затем перешли на новый релиз, где авторы поменяли структуру;
  • 💥 дубли появились раньше из-за сбоя: в логе были аварийные завершения, ручная правка таблиц, обмен с повторной загрузкой.

В сообщении обычно названо имя регистра. Если нет, смотрите журнал реструктуризации или текст ошибки целиком: в нём перечислены поля, по которым нарушена уникальность.

Что изменилось в регистреПочему появляются дублиЧто искать
Убрано измерениеСтроки сливаются по оставшимся полямГруппы с одинаковым набором оставшихся измерений
Периодичность стала грубееНесколько записей попадают в один периодЗаписи с датами внутри одного дня, месяца
Изменён тип измеренияЗначения приводятся к одному видуПустые и приведённые значения
Ручная правка таблицНарушен ключ физическиТочные повторы по всем полям

Шаг 1. Определите регистр и поля, по которым нет уникальности

Откройте Конфигуратор и найдите регистр в дереве: Конфигурация → Регистры сведений → нужный регистр. На вкладке «Данные» посмотрите список измерений и периодичность. Сравните с тем, что было до обновления: если у вас есть старая копия конфигурации, сделайте сравнение и объединение (Конфигурация → Сравнить, объединить с конфигурацией из файла).

Нужен итоговый список полей, которые будут составлять новый ключ. Именно по ним вы будете искать дубли. Запишите его: на следующем шаге он понадобится в запросе.

Если обновление вы ставили из окна «Обновление конфигурации» в режиме Предприятия, а не из Конфигуратора, ошибку всё равно увидите при реструктуризации. Не закрывайте окно с текстом, скопируйте его в блокнот.

Шаг 2. Найдите дубли запросом в консоли

Пока обновление не применилось, база работает на прежней конфигурации, и данные в регистре доступны. Откройте базу в режиме Предприятия под администратором и запустите консоль запросов (внешняя обработка «Консоль запросов» или та, что есть у вас в сборке).

Запрос группирует записи по будущему ключу и показывает группы, где строк больше одной:

ВЫБРАТЬ
    Рег.Организация КАК Организация,
    Рег.Номенклатура КАК Номенклатура,
    КОЛИЧЕСТВО(*) КАК Количество
ИЗ
    РегистрСведений.ИмяРегистра КАК Рег
СГРУППИРОВАТЬ ПО
    Рег.Организация,
    Рег.Номенклатура
ИМЕЮЩИЕ
    КОЛИЧЕСТВО(*) > 1

Подставьте своё имя регистра и своё поле ключа. Если регистр периодический, добавьте в группировку нужную часть периода: для периодичности «день» это НАЧАЛОПЕРИОДА(Рег.Период, ДЕНЬ).

Что смотреть в результате:

  1. Сколько групп. Три-пять групп можно поправить руками, несколько тысяч нужно чистить кодом или SQL.
  2. Одинаковы ли строки целиком. Если ресурсы в группе совпадают, лишнюю строку можно удалить без раздумий. Если различаются, нужно решить, какое значение правильное.
  3. Есть ли пустые значения. Строки с пустой ссылкой в измерении часто остаются от старых загрузок и безопасно удаляются, но сверьте с владельцем данных.

Чтобы увидеть сами строки, а не только счётчики, выведите ресурсы и период отдельным запросом по найденным ключам.

Шаг 3. Уберите лишние строки одним из способов

Выбор способа зависит от числа дублей и от того, кто работает с базой.

Сколько дублей нашёл запрос?

Способ А. Ручное удаление в режиме Предприятия

Подходит для небольшого числа записей. Откройте список регистра. Если у него нет пункта в интерфейсе, воспользуйтесь внешней обработкой для просмотра и правки регистров (подобные есть в сборках для администраторов) или консолью с выгрузкой результата. Далее:

  1. Отберите записи по значению одного из ключевых измерений (фильтр в списке).
  2. Сравните строки в группе по ресурсам.
  3. Выделите лишнюю строку и удалите её клавишей Delete, подтвердите удаление.
  4. Повторите проверку запросом из шага 2: он должен вернуть пустой результат.

Для периодических регистров список показывает период в первой колонке. Оставляйте строку с более поздней датой записи, если значения расходятся: она отражает последнее решение пользователя.

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

Способ Б. Удаление кодом по набору записей

Когда групп много, проще один раз написать выполняемый код во внешней обработке. Логика простая: выбрать дубли, сгруппировать, оставить одну строку из группы, остальные убрать через набор записей.

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    Набор = РегистрыСведений.ИмяРегистра.СоздатьНаборЗаписей();
    Набор.Отбор.Организация.Установить(Выборка.Организация);
    Набор.Отбор.Номенклатура.Установить(Выборка.Номенклатура);
    Набор.Прочитать();
    Если Набор.Количество() > 1 Тогда
        // оставляем последнюю по порядку, остальные удаляем
        Пока Набор.Количество() > 1 Цикл
            Набор.Удалить(0);
        КонецЦикла;
        Набор.Записать();
    КонецЕсли;
КонецЦикла;

Нюансы, на которых спотыкаются:

  • 🧪 Сначала прогоните код на копии базы и сравните число групп до и после.
  • ⏱ Для регистров с миллионами строк выборку делайте порциями, иначе процесс упрётся в память.
  • 🔒 Запускайте в монопольном режиме. Иначе пользователи успеют записать новые строки.
  • ✍️ Набор записей по неуникальному ключу в старой структуре читается нормально, но запись набора с отбором по неполному ключу заменит все найденные строки. Это ровно то, что нам нужно, но проверяйте отбор.

Способ В. Чистка средствами СУБД

Для администраторов, когда ни список, ни код не справляются с объёмом. Таблица регистра в SQL называется по схеме _InfoRg + номер, поля измерений называются _Fld + номер. Соответствие имён даёт метод ПолучитьСтруктуруХраненияБазыДанных(). Выполните его в консоли и найдите свой регистр по имени.

Пример для Microsoft SQL Server: оставить по одной строке в каждой группе дублей.

WITH d AS (
  SELECT ROW_NUMBER() OVER (
           PARTITION BY _Fld1234, _Fld1235
           ORDER BY _Period DESC) AS rn
  FROM _InfoRg1233
)
DELETE FROM d WHERE rn > 1;

Для PostgreSQL аналогичный приём делают через ctid:

DELETE FROM _inforg1233 a
USING _inforg1233 b
WHERE a._fld1234 = b._fld1234
  AND a._fld1235 = b._fld1235
  AND a.ctid < b.ctid;

Номера таблицы и полей здесь условные. Подставьте свои из структуры хранения. После чистки перезапустите сервер 1С или хотя бы очистите кеш сеансов, иначе клиенты будут видеть старые данные.

Прямой SQL обходит проверки платформы. Делайте его только при остановленных сеансах и с полной резервной копией. На файловой базе способ В недоступен: используйте А или Б.

После чистки: повторите обновление

Перед повтором убедитесь, что за время чистки никто не успел записать новые строки. Если база была открыта у пользователей, завершите их сеансы через консоль кластера серверов или в окне Администрирование → Активные пользователи.

Запустите тот же запрос из шага 2: результат должен быть пустым. Затем:

  1. В Конфигураторе нажмите F7 или Конфигурация → Обновить конфигурацию базы данных. Реструктуризация должна пройти без остановки.
  2. Если обновляли через «Обновление конфигурации» в режиме Предприятия, повторите установку того же файла обновления.
  3. Проверьте работу документов и отчётов, которые читают этот регистр.

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

Если ничего не помогло

Бывает, что дубли найдены и удалены, а ошибка повторяется. Чаще всего виноват неполный ключ в запросе или параллельный процесс, который снова пишет в регистр: регламентное задание, обмен, фоновый обработчик. Остановите их на время работы, а после обновления включите обратно.

Диагностика: выберите симптом

Ещё три запасных пути:

  • 🛠 Тестирование и исправление. Конфигуратор → Администрирование → Тестирование и исправление информационной базы. Включите проверку логической целостности и ссылочной целостности. Это не заменяет чистку дублей, но отсекает другие повреждения.
  • 📦 Выгрузка и загрузка. Выгрузите базу в .dt, загрузите в новую пустую. Иногда это снимает проблемы с физическим состоянием таблиц.
  • 🔙 Откат обновления. Если сроки горят, верните копию до обновления, поставьте старый релиз и разбирайтесь с дублями спокойно, пока бухгалтерия работает.

Как не получить дубли снова

Дубли не появляются из воздуха. Если почистили и забыли, через год они вернутся при очередном изменении структуры.

  • 📋 Перед обновлением типовой конфигурации с доработками смотрите список изменений структуры регистров в описании релиза.
  • 🔍 После каждого изменения измерений в своей конфигурации проверяйте данные запросом на тестовой копии, а не на боевой базе.
  • 🔄 Если регистр получает данные из обмена, настройте правила так, чтобы повторная загрузка заменяла записи, а не добавляла.
  • 🧹 Раз в квартал запускайте простой запрос на дубли по регистрам, которые вы дорабатывали.
Перед обновлением доработанной базы
Выполнено: 0 / 5

Частые вопросы

Можно ли просто отключить проверку уникальности и обновиться?
Нет. Уникальность ключа обеспечивает сама платформа при создании индекса, отключить её настройкой нельзя. Дубли нужно убрать из данных.
Какую из дублирующихся строк оставлять?
Ту, чьи значения ресурсов актуальнее. Для периодических регистров обычно оставляют запись с более поздней датой. Если строки расходятся по смыслу, согласуйте выбор с владельцем данных.
Как узнать номер таблицы регистра в SQL?
Выполните в консоли метод ПолучитьСтруктуруХраненияБазыДанных() и найдите регистр по имени. В результате будут и имя таблицы, и имена полей.
Затрагивает ли чистка движения документов?
Только если вы чистите регистр, в который документы делают движения. Для сведений такое бывает у подчинённых регистраторам регистров. Тогда удалять нужно через перепроведение, а не прямой записью.
Поможет ли «Тестирование и исправление» убрать дубли?
Само по себе нет, оно не знает, какую из строк считать лишней. Используйте его как дополнительную проверку после чистки.