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

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

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

Особенности периодичности и их влияние на запись

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

Ситуация усложняется, если включена Внутридневная, Дневная или Месячная периодичность. В таких регистрах к измерениям автоматически добавляется поле "Период". Это означает, что одна и та же сущность (например, курс доллара) может иметь разные значения в разные моменты времени. Чтобы изменить запись, вам необходимо точно указать не только измерения, но и конкретную дату времени, к которой относится изменение.

Существует также понятие "Ведущего периода". Если это свойство установлено, то при записи система контролирует, чтобы период записи не выходил за рамки периода существования объекта-владельца. Игнорирование этого правила приведет к ошибке выполнения. Поэтому перед тем как менять данные, всегда сверяйтесь с метаданными конфигурации.

💡

Всегда проверяйте свойство "Режим записи" в конфигураторе. Для большинства случаев подходит значение "Подчинение регламенту", но для оперативных данных иногда требуется "Независимый".

⚠️ Внимание: При изменении записей в регистре с периодичностью "День" и выше, платформа может автоматически округлять время до начала суток. Если ваша логика требует точности до секунды, убедитесь, что используется внутридневная периодичность, иначе данные могут записаться на соседнюю дату.

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

Алгоритм изменения в непериодических регистрах

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

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

  • 🔹 Создайте объект ЗаписьНабораДанных и укажите имя регистра.
  • 🔹 Сформируйте отбор по измерениям для поиска конкретной строки.
  • 🔹 Прочитайте данные из базы с помощью метода Прочитать().
  • 🔹 Измените значения полей ресурсов в полученном наборе.

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

Набор = Новый ЗаписьНабораДанных;

Набор.РегистрСведений = РегистрыСведений.КурсыВалют;

Набор.Отбор.Валюта.Установить(ВыбраннаяВалюта);

Набор.Прочитать();

// Далее изменение ресурсов и запись

Набор.Записать();

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

💡

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

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

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

Если вам необходимо изменить значение ресурса на конкретную дату, вы должны установить свойство Период у объекта записи. При этом стоит учитывать режим записи. В режиме "Подчинение регламенту" система может требовать, чтобы период записи совпадал с периодом документа-основания или текущей датой сеанса, если запись производится из формы.

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

Тип периодичности Поле периода Особенность записи Пример использования
Непериодический Отсутствует Только по измерениям Справочник валют
Внутридневная Период (ДатаВремя) Точность до секунды Остатки на складах
Дневная Период (Дата) Округление до дня Курсы валют ЦБ
Месячная Период (НачалоМесяца) Округление до месяца Штатное расписание

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

📊 С какой периодичностью регистров вы работаете чаще всего?
Непериодические
Внутридневные
Дневные
Месячные

Использование ЗаписьНабораДанных для обновления

Объект ЗаписьНабораДанных является основным инструментом для пакетного изменения записей. Его главное преимущество заключается в возможности загрузить группу записей, модифицировать их в памяти и одним вызовом сохранить изменения в базу. Это значительно эффективнее, чем выполнение отдельных запросов на обновление для каждой строки.

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

Рассмотрим пример, где необходимо обновить коэффициент для группы номенклатуры. Мы устанавливаем отбор по виду номенклатуры, читаем все соответствующие записи, проходим циклом по набору и меняем значение ресурса "Коэффициент". После выхода из цикла вызываем метод записи.

Набор = Новый ЗаписьНабораДанных;

Набор.РегистрСведений = РегистрыСведений.КоэффициентыНаценок;

Набор.Отбор.ВидНоменклатуры.Установить(НужныйВид);

Набор.Прочитать();

Для Каждого ТекЗапись Из Набор Цикл

ТекЗапись.Коэффициент = ТекЗапись.Коэффициент * 1.1;

КонецЦикла;

Набор.Записать();

Стоит отметить производительность такого подхода. При обновлении тысяч записей использование ЗаписьНабораДанных предпочтительнее циклического выполнения запросов ИЗМЕНЕНИЕ на языке запросов, так как последнее может блокировать таблицы и создавать лишнюю нагрузку на сервер СУБД. Однако для единичных правок разница незаметна.

⚠️ Внимание: Метод Прочитать() загружает данные в память клиента или сервера. Не пытайтесь прочитать весь огромный регистр без отборов, это может привести к исчерпанию оперативной памяти и падению сеанса 1С.

Поиск и обработка дублирующихся записей

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

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

  • 🔍 Выполните запрос с СГРУППИРОВАТЬ ПО всем измерениям регистра.
  • 🔍 Используйте условие ИМЕЮЩИЕ КОЛИЧЕСТВО(*) > 1 вHAVING.
  • 🔍 Полученный список используйте для формирования отбора в ЗаписьНабораДанных.
  • 🔍 Удалите лишние записи или объедините их значения вручную.

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

Как предотвратить дубли в будущем?

Всегда используйте конструкцию "Чтение-Модификация-Запись" через ЗаписьНабораДанных. Избегайте прямого создания новой записи, если не уверены на 100%, что такой комбинации измерений еще не существует в базе.

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

Обработка ошибок и транзакционность

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

Использование конструкций НачатьТранзакцию() и ЗафиксироватьТранзакцию() гарантирует, что либо все изменения будут сохранены, либо ни одно из них не применится (в случае отката). Это особенно актуально для сложных алгоритмов, где изменение одного регистра влечет за собой пересчет данных в других.

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

⚠️ Внимание: Длительные транзакции при записи в популярные регистры могут вызывать блокировки и замедлять работу других пользователей. Старайтесь минимизировать время удержания транзакции, выполняя тяжелые вычисления до её начала.

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

☑️ Контроль качества изменения данных

Выполнено: 0 / 5
Можно ли изменить запись в регистре сведений напрямую через запрос SQL?

Технически это возможно, если у вас есть прямой доступ к базе данных SQL, но категорически не рекомендуется. Платформа 1С использует сложные механизмы блокировок и кэширования. Прямая модификация таблиц SQL в обход API 1С может привести к рассинхронизации кэша, нарушению ссылочной целостности и невозможности проведения документов. Всегда используйте встроенные средства платформы: ЗаписьНабораДанных или запросы на языке 1С.

Что произойдет, если записать запись с периодом в прошлом в регистр с дневной периодичностью?

Запись будет успешно сохранена. Однако это изменит историю данных. Все срезы на момент времени, попадающие в интервал между старой записью и новой, теперь будут показывать новое значение. Это может потребовать перепроведения документов, которые использовали старое значение для своих расчетов.

Как узнать, была ли изменена запись фактически?

Объект ЗаписьНабораДанных не возвращает явного флага об изменении. Чтобы это отследить, нужно сравнить значения полей до и после модификации в цикле. Если ни одно значение ресурса не изменилось, можно не вызывать метод Записать() для этого набора, что сэкономит ресурсы базы данных.

В чем разница между ИзменитьЗаписи и Записать в ЗаписьНабораДанных?

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

Можно ли удалить запись из регистра сведений через ЗаписьНабораДанных?

Да. Для этого после чтения набора нужно установить свойство Запись.РежимЗаписи = РежимЗаписиРегистра.Удаление для конкретной строки или всего набора. При вызове метода Записать() эти строки будут физически удалены из таблицы регистра в базе данных.