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

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

При разработке нетиповых механизмов в 1С, особенно в конфигурациях уровня Управление торговлей 11 или ERP, разработчики часто сталкиваются с ошибкой при попытке записи набора данных в регистр сведений. Сообщение «Запись с такими ключевыми полями существует!» означает, что система пытается добавить в базу данных запись, которая дублирует уже существующий уникальный ключ (набор измерений), что недопустимо для архитектуры 1С.

Разбор природы ошибки

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

  1. Система анализирует установленный отбор (например, НаборЗаписей.Отбор.Регистратор.Установить(...)).
  2. Удаляются все записи в регистре, которые соответствуют данному отбору.
  3. В регистр записываются новые данные, которые находятся в объекте набора.

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

Способ решения №1: Подчинение регистратору (Рекомендуемый)

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

Рассмотрим шаги для реализации:

  1. Откройте конфигуратор и найдите ваш регистр сведений.
  2. Установите свойство «Режим записи» в значение «Подчинение регистратору».
  3. В списке регистраторов укажите ваш документ.

После этого Регистратор станет системным измерением. Теперь, когда вы вызываете НаборЗаписей.Отбор.Регистратор.Установить(Объект.Ссылка), система будет четко понимать, какие именно записи принадлежат текущему документу. При записи система корректно очистит только те движения, которые были созданы этим документом ранее, и запишет актуальные данные.

Способ решения №2: Расширение набора измерений

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

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


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

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

Способ решения №3: Использование периодического регистра

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

Важные советы по работе с данными

Анализируя ситуацию, важно помнить следующее:

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

← На главную