Как исправить ошибку «Запись с такими ключевыми полями существует» в 1С при работе с регистром сведений

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

При разработке в системе «1С:Предприятие» программисты часто сталкиваются с ситуацией, когда при проведении документа система выдает системную ошибку: «Запись с такими ключевыми полями существует!». Особенно часто эта проблема возникает при попытке записать данные из табличной части документа в периодический регистр сведений.

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

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

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

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


// Ошибочный вариант заполнения движений регистра сведений
Движения.ИсторияТС.Записывать = Истина;
Для Каждого ТекСтрокаДанные Из Данные Цикл
    Движение = Движения.ИсторияТС.Добавить();
    Движение.Период = Дата;
    Движение.ТС = ТС;
    Движение.Организация = Организация;
    
    // Заполнение ресурсов (ошибка: уникальность строк не обеспечена)
    Движение.Оборудование = ТекСтрокаДанные.Оборудование;
    Движение.НомерОборудования = ТекСтрокаДанные.НомерОборудования;
    Движение.ВидУслуги = ТекСтрокаДанные.ВидУслуги;
    Движение.СтоимостьРабот = ТекСтрокаДанные.СтоимостьРабот;
КонецЦикла;

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

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

В приведенном выше примере измерениями регистра являются только ТС (Транспортное средство) и Организация. Поля Оборудование, ВидУслуги и прочие были ошибочно добавлены в раздел «Ресурсы» или «Реквизиты».

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

  1. Период (равен дате документа Дата);
  2. Регистратор (ссылка на текущий документ);
  3. Измерение ТС;
  4. Измерение Организация.

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

Почему периодичность «По позиции регистратора» не решает проблему и вредит системе?

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

Более того, использование периодичности «По позиции регистратора» крайне не рекомендуется в профессиональной разработке по следующим причинам:

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

Как правильно решить проблему уникальности записей?

Рассмотрим два проверенных и архитектурно верных способа устранения этой ошибки.

Способ 1. Перенос аналитики из Ресурсов в Измерения

Если бизнес-логика вашей задачи подразумевает, что записи в рамках одного документа должны отличаться по смыслу (например, мы фиксируем установку разного оборудования на один автомобиль), то ключевую аналитику необходимо перенести из раздела «Ресурсы» в раздел «Измерения». В нашем примере измерением должно стать поле Оборудование или ВидУслуги.

В этом случае уникальный ключ на уровне базы данных будет состоять из полей: [Период] + [Регистратор] + [ТС] + [Организация] + [Оборудование]. Поскольку оборудование в каждой строке документа разное (например, «Масло» и «Фильтр»), уникальность записей будет соблюдена, и ошибка исчезнет.

Способ 2. Использование технического измерения (Ключ связи или Номер строки)

Бывают ситуации, когда в документе могут присутствовать абсолютно одинаковые строки (например, две одинаковые детали или две одинаковые услуги ремонта). В таком случае перенос реквизитов в измерения не спасет от ошибки дублирования.

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

Давайте посмотрим на пример правильного кода проведения документа с использованием измерения НомерСтрокиДокумента:


// Исправленный вариант проведения документа с техническим измерением
Движения.ИсторияТС.Записывать = Истина;
Для Каждого ТекСтрокаДанные Из Данные Цикл
    Движение = Движения.ИсторияТС.Добавить();
    Движение.Период = Дата;
    Движение.ТС = ТС;
    Движение.Организация = Организация;
    
    // Техническое измерение гарантирует уникальность каждой строки документа в БД
    Движение.НомерСтрокиДокумента = ТекСтрокаДанные.НомерСтроки;
    
    // Заполнение ресурсов и реквизитов
    Движение.Оборудование = ТекСтрокаДанные.Оборудование;
    Движение.НомерОборудования = ТекСтрокаДанные.НомерОборудования;
    Движение.ВидУслуги = ТекСтрокаДанные.ВидУслуги;
    Движение.СтоимостьРабот = ТекСтрокаДанные.СтоимостьРабот;
КонецЦикла;

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

Профессиональная архитектура учета «жизни» автомобиля

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

Разберем, как правильно спроектировать эту подсистему в соответствии со стандартами разработки «1С»:

1. Учет истории водителей (Экипаж ТС)

Для отслеживания того, кто в какой момент времени управлял автомобилем, идеально подходит Периодический регистр сведений с периодичностью Секунда.

Запрос СрезПоследних по этому регистру на любую дату мгновенно ответит на вопрос: «Кто был за рулем данного автомобиля в указанный момент времени?».

2. Состояния автомобиля (Диспозиция)

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

3. Ремонты и техническое обслуживание

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

4. Заправки и расход топлива (ГСМ)

Топливо — это материальный актив, имеющий количественный остаток в баке автомобиля. Нам необходимо контролировать приход (заправки) и расход (списание по нормам или факту).

Резюме

Мы выяснили причину возникновения ошибки дублирования записей регистра сведений и разобрали лучшие практики её устранения. Проектируя подсистемы учета в 1С, всегда четко разделяйте сущности: информацию о состояниях и свойствах объектов храните в регистрах сведений с уникальными наборами измерений, а информацию о затратах, объемах, расходах и остатках материальных ценностей — в специализированных регистрах накопления.

← На главную