При переносе больших массивов данных между базами 1С разработчики нередко прибегают к прямой работе с таблицами СУБД через запросы INSERT INTO. Это позволяет избежать длительной выгрузки и загрузки файлов через стандартные механизмы конвертации данных. Однако при таком подходе можно столкнуться со странным поведением платформы: данные в регистр перенесены, записи видны в интерфейсе, но поле Регистратор остается полностью пустым, не выводя даже привычную битую ссылку <Объект не найден>.
Разберем детально, как устроено хранение регистратора на уровне СУБД, выясним причину возникновения пустого значения и проанализируем, как корректно решить эту задачу и избежать критических ошибок при прямой работе с базой данных.
Поле Регистратор в подчиненных регистрах сведений, накопления и бухгалтерии является составным ссылочным типом данных. В базе данных для хранения такого поля платформа выделяет не одну, а две служебные колонки:
_RecorderTRef — бинарный идентификатор типа метаданных (код конкретной таблицы документа-регистратора в текущей конфигурации);_RecorderRRef — непосредственно уникальный идентификатор (GUID) конкретного документа в формате binary(16).Поведение платформы при отображении регистратора зависит от корректности каждого из этих полей:
_RecorderTRef указан верно (соответствует объекту, входящему в список допустимых регистраторов данного регистра), но ссылка в _RecorderRRef не существует в соответствующей таблице документа, 1С выводит строку <Объект не найден...>._RecorderTRef не существует в текущей структуре метаданных базы-приемника или не входит в перечень разрешенных типов регистраторов для этой таблицы, платформа не может инициализировать составной тип данных. В результате значение расценивается как некорректный тип и интерпретируется как пустое значение (Неопределено).Коды типов метаданных (TRef) генерируются платформой динамически при создании и реструктуризации объектов. Если база-источник и база-приемник отличаются версиями конфигурации (например, УТ 10.3.19 и УТ 10.3.40) либо в одной из них выполнялись доработки структуры, идентификаторы таблиц в СУБД для одного и того же типа документа неизбежно разойдутся.
Например, для документа «Корректировка записей регистров» код типа в базе-источнике может иметь значение 0x000000AE, а в обновленной базе-приемнике — 0x000000C3. Простое копирование исходного значения приводит к тому, что СУБД возвращает неизвестный для новой конфигурации код, и поле регистратора отображается пустым.
Для исправления ситуации выполним следующие шаги:
_RecorderTRef:
SELECT TOP 1 _RecorderTRef, _RecorderRRef
FROM dbo._InfoRg8560
WHERE _RecorderRRef = 0x...; -- GUID созданного тестового документа
UPDATE dbo._InfoRg8560
SET _RecorderTRef = 0x000000C3
WHERE _RecorderTRef = 0x000000AE;
Если при манипуляциях с базой данных требуется вручную сопоставлять ссылки документов, необходимо помнить об особенностях хранения уникальных идентификаторов в 1С. Платформа использует специфический порядок байтов (byte swap) при переводе строкового GUID в бинарное поле binary(16).
Рассмотрим структуру строкового GUID вида: AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE. При сохранении в поле СУБД байты переставляются следующим образом:
DDDD и блок EEEEEEEEEEEE без изменений порядка байтов.CCCC с реверсом, затем блок BBBB с реверсом, и в конце блок AAAAAAAA с реверсом.Прямое преобразование через функции СУБД без учета реверса байтов приведет к поиску несуществующей ссылки.
Прямая вставка записей в таблицы СУБД в обход сервера приложений 1С влечет за собой серьезные риски нарушить целостность данных:
_RecorderTRef, _RecorderRRef и _LineNo (номер строки). Нумерация строк для каждого регистратора обязана начинаться строго с 1 и идти последовательно без пропусков и дублирования. При нарушении нумерации штатное чтение набора записей завершится ошибкой.INSERT наполняет только таблицу движений. Таблицы итогов (остатков и оборотов) не обновляются. Виртуальные таблицы отчетов и запросов будут возвращать пустые или неверные данные до принудительного пересчета итогов в режиме «Тестирование и исправление» или обработке «Управление итогами»._ChngR*. Данные не уйдут в узлы РИБ и внешние интеграции без ручного вызова метода ПланыОбмена.ЗарегистрироватьИзменения().Чтобы исключить риски повреждения служебных структур СУБД, для массовой загрузки данных рекомендуется использовать оптимизированные штатные механизмы платформы:
РегистрСведенийНаборЗаписей с установкой свойства загрузки данных перед сохранением:
Набор = РегистрыСведений.ЦеныАТТ.СоздатьНаборЗаписей();
Набор.Отбор.Регистратор.Установить(ДокументСсылка);
Набор.ОбменДанными.Загрузка = Истина;
// Заполнение набора записей
Набор.Записать();
ОбменДанными.Загрузка = Истина отключает выполнение подписок на события, проверку прав и обработчики проведения, что приближает скорость записи к прямому обращению к СУБД.
РегистрыНакопления[ИмяРегистра].УстановитьИспользованиеИтогов(Ложь). После завершения всей загрузки итоги включаются обратно с однократным пересчетом.ФоновыеЗадания.Выполнить().