Как исправить ошибку «Записи регистра сведений стали неуникальными» для регистра «СоставДокументовЗарплатаКадры» в 1С:ЗУП и 1С:ЗиКГУ

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом IT и автоматизация бизнеса
← На главную

В процессе сопровождения и обновления программных продуктов «1С:Зарплата и управление персоналом» (ЗУП 3.1) и «1С:Зарплата и кадры государственного учреждения» (ЗиКГУ 3.1) технические специалисты нередко сталкиваются со сбоем на этапе реорганизации базы данных. Платформа выдает критическую ошибку: «Записи регистра сведений стали неуникальными», прерывая процесс обновления конфигурации. Чаще всего проблемным объектом оказывается независимый непериодический регистр сведений СоставДокументовЗарплатаКадры.

В этой статье мы подробно проанализируем, для чего предназначен данный регистр, почему в нем физически могут появляться дублирующие записи, и рассмотрим несколько практических методов устранения этой ошибки — от использования встроенного языка 1С до низкоуровневых запросов на стороне СУБД.

Назначение регистра «СоставДокументовЗарплатаКадры»

Прежде чем переходить к устранению неполадок, разберем архитектурное назначение этого объекта метаданных. Регистр сведений СоставДокументовЗарплатаКадры является служебным (техническим). Он предназначен для оптимизации работы динамических списков в различных кадровых и расчетных журналах документов (таких как «Все начисления», «Кадровые документы», «Ведомости в банк/кассу» и др.).

В современных конфигурациях на платформе 1С:Предприятие 8.3 активно используется механизм разграничения прав доступа на уровне записей (RLS — Record Level Security). Если бы при открытии списков документов система каждый раз обращалась к табличным частям сотен тысяч документов для фильтрации по конкретному физическому лицу, сотруднику или подразделению, это вызывало бы огромные задержки и блокировки базы данных.

Для решения этой проблемы разработчики спроектировали механизм трансляции состава документов в плоскую таблицу. При записи или проведении любого документа, содержащего сведения о сотрудниках, система автоматически регистрирует связку в регистре СоставДокументовЗарплатаКадры. Динамические списки журналов делают быстрое левое соединение (LEFT JOIN) с этим регистром, мгновенно отсекая документы, к которым у текущего пользователя нет прав доступа, или выполняя быстрые пользовательские отборы.

Почему для одной строки документа создаются две записи?

Измерениями регистра сведений СоставДокументовЗарплатаКадры являются всего два поля:

  1. ФизическоеЛицо (тип СправочникСсылка.ФизическиеЛица)
  2. ДокументФизическогоЛица (ссылка на документ, сделавший запись)

Поскольку регистр является независимым и непериодическим, сочетание значений этих двух измерений образует уникальный ключ записи СУБД. Платформа физически не допускает существования двух абсолютно одинаковых строк с одинаковым набором измерений.

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

Суть ошибки уникальности при обновлении или откате релиза

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

Это происходит из-за того, что в новой (или старой) версии конфигурации меняется структура регистра сведений (например, изменяется состав или типы измерений). На уровне СУБД платформа пытается пересоздать уникальный индекс таблицы. Если в текущей базе данных уже содержатся дублирующие записи (которые ранее могли быть записаны из-за программного бага), СУБД не может построить индекс по неуникальным полям и прерывает трансляцию изменений.

Ниже мы разберем по шагам три проверенных метода локализации и устранения этой ошибки.

Способ А. Поиск и удаление дубликатов на уровне СУБД (для клиент-серверных баз)

Если ваша информационная база развернута на SQL-сервере (MS SQL Server, PostgreSQL), наиболее быстрым и эффективным решением будет прямая работа с таблицами базы данных.

Сначала нам нужно определить физическое имя таблицы регистра сведений в СУБД. Для этого в конфигураторе воспользуемся функцией ПолучитьСтруктуруХраненияБазыДанных() или выполним поиск по имени объекта метаданных. Предположим, что имя таблицы нашего регистра в СУБД — _InfoRg20542 (где 20542 — уникальный внутренний идентификатор объекта).

Выполним следующий SQL-запрос для поиска записей, нарушающих уникальность:


SELECT f_id, doc_id, COUNT(*) 
FROM _InfoRg20542 -- укажите имя таблицы вашего регистра
GROUP BY f_id, doc_id 
HAVING COUNT(*) > 1;

Для удаления дубликатов и сохранения только одной уникальной строки можно воспользоваться конструкцией с обобщенным табличным выражением (CTE):


WITH CTE_Duplicates AS (
    SELECT f_id, doc_id,
           ROW_NUMBER() OVER (PARTITION BY f_id, doc_id ORDER BY (SELECT NULL)) as RowNum
    FROM _InfoRg20542
)
DELETE FROM CTE_Duplicates WHERE RowNum > 1;

После выполнения данного запроса на стороне СУБД все дублирующиеся строки будут удалены, и обновление конфигурации в Конфигураторе успешно завершится.

Способ Б. Устранение дублей через обработку в пользовательском режиме 1С

Если база работает в файловом режиме или у вас нет прямого доступа к консоли СУБД, мы можем найти и исправить данные программными средствами 1С. Для этого необходимо запустить базу в пользовательском режиме (на исходном релизе конфигурации до начала обновления) и воспользоваться консолью запросов.

Напишем запрос на встроенном языке 1С для выявления дублирующих записей:


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

Результат = Запрос.Выполнить();

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

Способ В. Кардинальный и самый быстрый метод — временная очистка регистра

Так как этот регистр выполняет чисто техническую функцию и не хранит уникальных расчетных данных, мы можем полностью его очистить перед обновлением, а затем восстановить данные автоматически.

Рассмотрим этот надежный алгоритм по шагам:

  1. Обязательно создайте резервную копию (архив) информационной базы перед проведением любых технических работ!
  2. Запустите базу данных в режиме «1С:Предприятие» и выполните в обработке или внешней консоли короткий программный код для полной очистки записей регистра:
  3. 
    Набор = РегистрыСведений.СоставДокументовЗарплатаКадры.СоздатьНаборЗаписей();
    Набор.Записать(Истина);
    
  4. Закройте пользовательский сеанс и запустите Конфигуратор.
  5. Выполните обновление конфигурации. Так как таблица регистра теперь абсолютно пустая, реорганизация структуры пройдет мгновенно и без ошибок уникальности.
  6. После успешного обновления запустите базу в пользовательском режиме. Перейдите в меню Администрирование — Обслуживание — Обновление программы — Результаты обновления.
  7. Перейдите по ссылке «Запуск отложенных обработчиков обновления». Система автоматически в фоновом режиме запустит перерасчет и заново заполнит регистр СоставДокументовЗарплатаКадры актуальными и корректными данными на основании всех проведенных документов базы.

Использование этого метода полностью исключает риск повторного возникновения ошибки реорганизации данных и позволяет обновить систему в кратчайшие сроки.

← На главную