Как добавить записи в регистр сведений и не удалить существующие данные

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

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

Проблема использования НабораЗаписей без отбора

Проанализируем типичную ошибку начинающих разработчиков. Часто кажется, что достаточно создать объект СоздатьНаборЗаписей, добавить в него строку и вызвать метод Записать(). Однако по умолчанию метод Записать() вызывается с параметром Истина (режим замещения). Если при этом у набора записей не установлен Отбор, система воспримет это как команду: "Заменить все записи в регистре на те, что сейчас находятся в наборе". Если в наборе одна строка — останется одна. Если набор пустой — регистр будет очищен полностью.

Рассмотрим ситуацию: нам нужно добавить значение свойства для договора. Посмотрим на пример кода, который безопасно решает эту задачу через НаборЗаписей:


НаборЗаписейЗначенияСвойств = РегистрыСведений.ЗначенияСвойствОбъектов.СоздатьНаборЗаписей();

// Установка отбора — КРИТИЧЕСКИ ВАЖНЫЙ ЭТАП
НаборЗаписейЗначенияСвойств.Отбор.Объект.Установить(ДоговорСсылка);
НаборЗаписейЗначенияСвойств.Отбор.Свойство.Установить(СвойствоП);

// Читаем текущие данные из БД по этому отбору
НаборЗаписейЗначенияСвойств.Прочитать();

Если НаборЗаписейЗначенияСвойств.Количество() > 0 Тогда
    // Если запись уже есть, меняем ресурс
    Запись = НаборЗаписейЗначенияСвойств[0];
    Запись.Значение = ЗначениеП;
Иначе
    // Если записи нет, добавляем новую
    Запись = НаборЗаписейЗначенияСвойств.Добавить();
    Запись.Объект = ДоговорСсылка;
    Запись.Свойство = СвойствоП;
    Запись.Значение = ЗначениеП;
КонецЕсли;

// Записываем набор. Теперь удалятся только записи, 
// соответствующие отбору (Договор + Свойство)
НаборЗаписейЗначенияСвойств.Записать();

Метод Записать(Ложь) и его нюансы

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

Использование МенеджераЗаписи для точечных правок

Для работы с одной конкретной записью в независимом регистре сведений часто удобнее использовать МенеджерЗаписи. Разберем по шагам, как он работает. Менеджер записи "заточен" под работу с одной строкой таблицы. Он позволяет прочитать конкретную запись по ключу, изменить её или создать новую, если старой не нашлось.


МенеджерЗаписи = РегистрыСведений.ЗначенияСвойствОбъектов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Объект = ДоговорСсылка;
МенеджерЗаписи.Свойство = СвойствоП;

// Пытаемся найти существующую запись
МенеджерЗаписи.Прочитать();

// Устанавливаем новое значение ресурса
МенеджерЗаписи.Значение = ЗначениеП;

// Записываем. Если запись была — она обновится. 
// Если не было — создастся новая. Остальной регистр не пострадает.
МенеджерЗаписи.Записать();

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

Различия между независимыми и подчиненными регистрами

Проанализируем ситуацию с регистрами, которые имеют режим записи "Подчинение регистратору". В таких регистрах нельзя просто создать менеджер записи или набор с произвольным отбором. Все записи жестко привязаны к документу-регистратору. Чтобы добавить запись и не удалить другие, нужно:

  1. Работать через свойство Движения документа-регистратора.
  2. Использовать НаборЗаписей с обязательным отбором по конкретному регистратору.

Если вы запишете пустой набор с отбором по регистратору "ДокументОбъект.Ссылка", вы очистите движения только этого документа, что является штатной операцией перепроведения.

Особенности блокировок и производительности

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

Работа с периодическими регистрами

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

Посмотрим на пример изменения ресурса в периодическом регистре:


Набор = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей();
Набор.Отбор.Период.Установить(НужнаяДата);
Набор.Отбор.Валюта.Установить(СсылкаВалюта);

Набор.Прочитать();
Если Набор.Количество() > 0 Тогда
    Набор[0].Курс = НовыйКурс;
    Набор.Записать();
КонецЕсли;

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

← На главную