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

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

В процессе разработки и кастомизации конфигураций на платформе 1С:Предприятие разработчики часто сталкиваются с классической ошибкой проектирования базы данных: попыткой хранить историю событий или изменений состояний в непериодическом независимом регистре сведений. Типичный симптом такой ошибки — системное сообщение об ошибке: «Запись с такими ключевыми полями уже существует» при попытке повторить ранее выполненное действие.

В этой статье мы подробно проанализируем, почему возникает эта ошибка на примере кадрового учета, разберем, почему популярные «костыли» (обходные пути) опасны для производительности системы, и рассмотрим правильные архитектурные решения этой проблемы.

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

Рассмотрим стандартную бизнес-ситуацию. Сотрудник компании совершает цепочку перемещений:

  1. Принят в Отдел продаж на должность Менеджер (01.01.2023).
  2. Переведен в Отдел маркетинга на должность Маркетолог (01.06.2023).
  3. Переведен обратно в Отдел продаж на должность Менеджер (01.12.2023).

В регистре сведений, который спроектирован как непериодический, ключевыми полями (измерениями) выступают: Сотрудник, Отдел и Должность. Дата перемещения при этом ошибочно записывается в ресурсы регистра.

Для платформы 1С уникальность записи в регистре сведений определяется исключительно набором значений его измерений. С точки зрения СУБД, измерения составляют первичный ключ таблицы. Когда мы пытаемся записать третью операцию (возврат в тот же отдел на ту же должность), платформа видит, что запись с измерениями «Иванов — Отдел продаж — Менеджер» уже существует в базе данных. Тот факт, что дата перемещения (хранящаяся в ресурсах) отличается, платформой игнорируется. Происходит конфликт уникальности, и система блокирует запись.

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

Анализ нерекомендуемого решения («костыля»)

Иногда разработчики пытаются обойти ограничение СУБД самым простым и очевидным путем — добавлением нового измерения, например, НомерПеремещения (типа Число, Строка или уникальный идентификатор GUID), в которое при каждой записи помещается новое уникальное значение.

Выясним причину, почему такое решение является крайне нежелательным:

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


ВЫБРАТЬ
    Кадры.Сотрудник,
    Кадры.Отдел,
    Кадры.Должность,
    Кадры.ДатаПеремещения
ИЗ
    РегистрСведений.КадровыеДанные КАК Кадры
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ (
        ВЫБРАТЬ
            Сотрудник КАК Сотрудник,
            МАКСИМУМ(НомерПеремещения) КАК МаксНомер
        ИЗ
            РегистрСведений.КадровыеДанные
        СГРУППИРОВАТЬ ПО
            Сотрудник
    ) КАК МаксДанные 
    ПО Кадры.Сотрудник = МаксДанные.Сотрудник 
    И Кадры.НомерПеремещения = МаксДанные.МаксНомер

На больших базах данных (с десятками тысяч сотрудников и историей за несколько лет) такое соединение вызовет серьезное падение производительности и увеличит нагрузку на СУБД.

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

---

Правильные архитектурные решения

Рассмотрим подробнее три профессиональных способа решения этой проблемы в зависимости от контекста задачи.

Вариант 1. Сделать регистр сведений периодическим

Это самый естественный и правильный способ хранения истории изменений в 1С. Периодические регистры сведений специально созданы для фиксации состояний во времени.

Разберем по шагам, как это реализовать:

  1. Откройте свойства вашего регистра сведений в конфигураторе.
  2. На вкладке «Основные» найдите свойство «Периодичность».
  3. Установите значение, соответствующее бизнес-логике (например, В пределах секунды или В пределах дня).
  4. Удалите ресурс ДатаПеремещения, так как теперь его роль будет выполнять стандартное системное измерение Период.

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


ВЫБРАТЬ
    Срез.Сотрудник,
    Срез.Отдел,
    Срез.Должность,
    Срез.Период КАК ДатаПеремещения
ИЗ
    РегистрСведений.КадровыеДанные.СрезПоследних(&Период, ) КАК Срез

Вариант 2. Перевод регистра в режим «Подчинение регистратору»

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

Проанализируем преимущества этого подхода:

В этом случае уникальность записей на уровне СУБД будет обеспечиваться комбинацией полей: Период + Регистратор + НомерСтроки. Это полностью исключает возникновение ошибок дублирования, даже если сотрудника перемещают несколько раз за одну секунду разными документами.

Вариант 3. Использование измерения «Документ-основание»

Если по каким-то причинам регистр сведений должен оставаться независимым и непериодическим (что бывает крайне редко при проектировании кадрового учета), то вместо бессмысленного числового счетчика добавьте измерение ДокументОснование (с типом ссылки на документ перемещения).

Поскольку каждый документ в системе имеет уникальную ссылку (GUID), это гарантирует уникальность записей в регистре. Данный подход сохраняет понятную бизнес-логику связей объектов базы данных и упрощает построение отчетов.

---

Нюансы разработки в расширениях конфигурации

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

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

В таком сценарии правильным решением будет:

  1. Создать собственный новый периодический регистр сведений непосредственно внутри вашего расширения.
  2. Настроить запись кадровых данных из расширяемых форм или документов в ваш новый регистр.
  3. Использовать созданный регистр для построения кастомной отчетности, не затрагивая структуру типовых объектов конфигурации.
← На главную