При разработке механизмов сохранения данных в регистры сведений часто возникает досадная ошибка: «Запись с такими ключевыми полями существует». Давайте вместе разберемся, почему она появляется, что происходит в недрах платформы 1С и как правильно организовать запись данных, чтобы избежать конфликтов и потери информации.
В платформе 1С Регистр сведений — это объект, структура которого определяется его измерениями. Именно измерения формируют ключ уникальности записи. Если у вас в регистре МойРС измерением является только Договор, то в базе данных для каждого конкретного договора может существовать только одна-единственная запись.
Когда вы пытаетесь добавить новую строку с тем же договором, который уже есть в регистре, система выдает ошибку. Она справедливо считает, что вы нарушаете условие уникальности ключа, так как не понимает, должны ли новые данные заменить старые или вы пытаетесь создать дубль.
Прежде чем писать код, важно определить, как именно должны храниться данные. Рассмотрим несколько сценариев:
Период. Теперь для одного договора можно будет хранить десятки записей с разными датами.ДатаСтатуса в измерения регистра. Тогда уникальной будет комбинация Договор + ДатаСтатуса. Это позволит фиксировать разные статусы для одного договора, если они относятся к разным датам.Отбора в наборе записей.Частая ошибка — попытка добавлять записи в НаборЗаписей без предварительной настройки отбора. Если вы не установите отбор, набор записей при методе Записать() попытается записать всё, что в нем есть, не учитывая, что в базе уже могут быть конфликтующие данные. Чтобы работать корректно, давайте посмотрим на правильный алгоритм:
Для перезаписи данных конкретного договора необходимо сначала установить отбор, чтобы платформа понимала, какую именно область данных мы собираемся обновлять.
Процедура ЗаписатьСтатусДоговора(СтрокаТаблицы)
// Создаем набор записей
НаборЗаписей = РегистрыСведений.МойРС.СоздатьНаборЗаписей();
// Устанавливаем отбор по измерению Договор
// Это позволит нам работать только с записями конкретного договора
НаборЗаписей.Отбор.Договор.Установить(СтрокаТаблицы.Договор);
// Добавляем новую запись
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Договор = СтрокаТаблицы.Договор;
НоваяЗапись.Статус = СтрокаТаблицы.Статус;
НоваяЗапись.Дата = СтрокаТаблицы.ДатаСтатуса;
НоваяЗапись.Комментарий = СтрокаТаблицы.Комментарий;
// Записываем данные
// Метод Записать() с параметром Истина при установленном отборе
// автоматически перезапишет старые записи новыми для этого договора
НаборЗаписей.Записать(Истина);
КонецПроцедуры
Если вам нужно обработать только одну запись и вы не хотите использовать пакетную обработку через набор записей, воспользуйтесь объектом РегистрСведенийМенеджерЗаписи. Это удобный инструмент для точечной работы.
Алгоритм действий с менеджером записи:
СоздатьМенеджерЗаписи().Договор).Прочитать(). Если запись существует, объект заполнится текущими данными из базы.Записать().Этот способ идеален, если логика программы подразумевает работу с конкретным объектом договора, так как он берет на себя всю рутину по проверке существования записи.
Для того чтобы избежать ошибки нарушения уникальности:
НаборЗаписей, обязательно используйте Отбор, чтобы ограничить область перезаписи.НаборЗаписей.Добавить() в цикле без предварительной очистки или установки отбора — это гарантированно приведет к ошибкам при повторном запуске обработки.НаборЗаписей для массовых операций (пакетов данных), МенеджерЗаписи для работы с конкретной строкой.Теперь, применив эти знания, вы сможете настроить сохранение статусов договоров надежно и без конфликтов с платформой 1С!