Как изменить записи и измерения в независимом регистре сведений 1С

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

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

Постановка задачи

Представим ситуацию: в системе есть независимый регистр сведений. Нам необходимо отобрать первые 20 записей, в которых определенное измерение (например, Контрагент или Склад) не заполнено, и записать в это измерение нужное нам значение. Сложность заключается в том, что измерения в 1С формируют уникальный ключ записи. Изменение ключа — это всегда критическая операция для базы данных.

Решение через МенеджерЗаписи: пошаговый разбор

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

Для начала нам необходимо выбрать нужные записи с помощью запроса. Проанализируем пример кода:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 20
    |   МойРегистр.Измерение1 КАК Измерение1,
    |   МойРегистр.Измерение2 КАК Измерение2
    |ИЗ
    |   РегистрСведений.МойРегистр КАК МойРегистр
    |ГДЕ
    |   МойРегистр.Измерение2 = &ПустоеЗначение";

Запрос.УстановитьПараметр("ПустоеЗначение", ""); // Для строки - "", для ссылок - ЗначениеЗаполнено()
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

НачатьТранзакцию();
Попытка
    Пока Выборка.Следующий() Цикл
        // Создаем менеджер записи для конкретной строки
        МенеджерЗаписи = РегистрыСведений.МойРегистр.СоздатьМенеджерЗаписи();
        
        // Устанавливаем текущие значения измерений (фильтр для поиска записи)
        МенеджерЗаписи.Измерение1 = Выборка.Измерение1;
        МенеджерЗаписи.Измерение2 = Выборка.Измерение2;
        
        // Читаем запись из базы данных
        МенеджерЗаписи.Прочитать();
        
        Если МенеджерЗаписи.Выбран() Тогда
            // Устанавливаем НОВОЕ значение измерения
            МенеджерЗаписи.Измерение2 = "НовоеЗначение";
            
            // Записываем. Система сама удалит старую запись и создаст новую
            МенеджерЗаписи.Записать(Истина);
        КонецЕсли;
    КонецЦикла;
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    ЗаписьЖурналаРегистрации("Ошибка изменения регистра", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
КонецПопытки;

Важный нюанс: Обратите внимание на использование НачатьТранзакцию(). При изменении данных в цикле крайне важно оборачивать процесс в транзакцию. Это гарантирует, что если на 15-й записи произойдет сбой, база данных вернется в исходное состояние, и у вас не возникнет «частичного» обновления данных.

Специфика изменения измерений

Разберем, что происходит «под капотом» платформы 1С. В регистрах сведений измерения составляют уникальный ключ. Технически «изменить» значение измерения в существующей записи невозможно. Когда вы меняете значение через МенеджерЗаписи и вызываете Записать(), платформа выполняет две операции: удаление записи со старым набором измерений и вставку новой записи.

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

Использование НабораЗаписей: когда это эффективно?

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

Выясним, как обойти это ограничение. Рассмотрим профессиональный алгоритм для работы с «ТОП N» записей:

  1. Выполняем запрос, который выбирает все измерения, составляющие уникальный ключ.
  2. Выгружаем результат запроса в таблицу значений или массив структур.
  3. Для каждой строки из таблицы значений создаем отдельный НаборЗаписей.
  4. Устанавливаем точный отбор по всем измерениям (чтобы в набор попала ровно одна конкретная запись).
  5. Читаем набор, меняем данные и записываем.

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


Набор = РегистрыСведений.МойРегистр.СоздатьНаборЗаписей();
// Устанавливаем отбор по старым значениям
Набор.Отбор.Измерение1.Установить(СтароеЗначение1);
Набор.Отбор.Измерение2.Установить(СтароеЗначение2);
Набор.Прочитать();

Если Набор.Количество() > 0 Тогда
    Запись = Набор[0];
    // Меняем измерение
    Запись.Измерение2 = НовоеЗначениеИзмерения;
    
    // ВАЖНО: Перед записью нужно очистить отбор, так как значение Измерение2 изменилось
    Набор.Отбор.Измерение2.Установить(НовоеЗначениеИзмерения);
    Набор.Записать();
КонецЕсли;

Производительность и блокировки данных

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

Рекомендуется перед циклом изменения устанавливать управляемую блокировку именно на те комбинации измерений, которые вы собираетесь модифицировать. Это предотвратит возникновение ошибки Lock conflict (конфликт блокировок). Для этого используется объект БлокировкаДанных.

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

Резюме

Подводя итоги, можно выделить основные правила изменения записей в независимом регистре:

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

← На главную