Как преобразовать независимый регистр сведений в подчиненный регистратору и сохранить данные

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

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

Почему данные исчезают при изменению режима записи?

Прежде чем мы перейдем к методам решения, проанализируем техническую сторону вопроса. В системе 1С структура таблиц СУБД для независимых и подчиненных регистров принципиально различается. Для независимого регистра ключом уникальности является только комбинация его измерений. Для подчиненного регистра платформа автоматически добавляет в структуру таблицы два обязательных системных поля: Регистратор (ссылка на документ) и НомерСтроки (целое число).

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

Метод 1: Переименование регистра и создание нового (самый безопасный)

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

  1. Переименуем в конфигураторе старый независимый регистр (например, ЦеныНоменклатуры в Удалить_ЦеныНоменклатуры).
  2. Создадим новый регистр сведений с исходным именем (ЦеныНоменклатуры) и установим для него режим записи "Подчинение регистратору". Настроим состав измерений, ресурсов и реквизитов идентично старому регистру.
  3. Назначим для нового регистра необходимые документы-регистраторы.
  4. Обновим конфигурацию базы данных. Теперь у нас есть пустой рабочий регистр и старый регистр с данными.
  5. Напишем и запустим обработку переноса данных.

Проанализируем пример кода для переноса данных из старого регистра в новый. Допустим, мы решили, что регистратором для старых записей станет специально созданный документ "Корректировка записей регистров":


// Пример переноса данных между регистрами
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   *
    |ИЗ
    |   РегистрСведений.Удалить_ЦеныНоменклатуры КАК СтарыйРегистр";

Выборка = Запрос.Выполнить().Выбрать();

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

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

Метод 2: Выгрузка в промежуточную таблицу (для небольших объемов)

Если в регистре не слишком много записей (например, до 100-200 тысяч), мы можем использовать способ с сохранением данных в оперативную память. Рассмотрим этот процесс по шагам:

  1. Создадим внешнюю обработку, которая считывает все записи регистра в ТаблицаЗначений.
  2. Сохраним эту таблицу во внешний файл (например, через ЗначениеВФайл или используя XML-сериализацию).
  3. В конфигураторе сменим режим регистра на "Подчинение регистратору", добавим регистраторы и обновим базу (данные очистятся).
  4. Загрузим данные из файла обратно в регистр, программно заполняя поле Регистратор.

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

Метод 3: Прямое манипулирование на уровне SQL (для экспертов)

Рассмотрим ситуацию, когда в регистре миллионы записей, и программный перенос через объекты 1С займет слишком много времени. В этом случае проанализируем возможность работы напрямую с СУБД (MS SQL или PostgreSQL). Внимание: данный метод не поддерживается фирмой 1С и может привести к неработоспособности базы, если не соблюдать осторожность.

Логика работы на уровне SQL выглядит следующим образом:

  1. Создаем временную таблицу в SQL и копируем в нее данные из таблицы регистра.
  2. В конфигураторе 1С меняем тип регистра на подчиненный и обновляем базу. Платформа пересоздаст таблицу с новыми полями _Period, _RecorderTRef, _RecorderRRef, _LineNo и _Active.
  3. С помощью SQL-запроса INSERT INTO ... SELECT переносим данные из временной таблицы в основную.
  4. Главная сложность — корректно заполнить системные поля. Поле _RecorderRRef должно содержать GUID документа-регистратора в бинарном виде, а _LineNo — уникальный порядковый номер внутри каждого регистратора.

Посмотрим на пример логики заполнения _LineNo средствами SQL. Можно использовать оконную функцию ROW_NUMBER() OVER(PARTITION BY ... ORDER BY ...), чтобы сформировать правильную нумерацию строк для каждого документа.

Важные технические нюансы, о которых нельзя забывать

Проанализируем дополнительные параметры, которые появляются у подчиненного регистра и требуют обязательного заполнения:

Выводы и рекомендации

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

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

← На главную