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