При интеграции 1С со сторонними системами (например, интернет-магазинами, внешними базами данных или аналитическими хранилищами) разработчики часто сталкиваются с задачей выгрузки движений регистров. Логика интеграции требует, чтобы у каждой выгружаемой строки был собственный уникальный идентификатор (UUID/GUID). Попробуем разобраться, существует ли у записи регистра накопления собственный GUID на уровне платформы и СУБД, и как правильно решить задачу уникальной идентификации строк.
Проанализируем архитектуру хранения данных в платформе 1С:Предприятие. Уникальный идентификатор (GUID) присваивается только ссылочным типам данных — элементам справочников, документам, планам видов характеристик, планам счетов и бизнес-процессам. Записи регистров накопления ссылочными сущностями не являются.
В физических таблицах СУБД (MS SQL Server, PostgreSQL) для движений регистров накопления отдельное поле первичного ключа типа GUID отсутствует. Кластерный индекс и уникальность строки определяются комбинацией двух обязательных системных полей:
_RecorderTRef для типа и _RecorderRRef для бинарного GUID документа)._LineNo).Также важно понимать, как работает механизм распределенных информационных баз (РИБ). При передаче изменений регистрация ведется не по отдельным строкам, а по документу-регистратору целиком. В базу-приемник передается весь набор записей документа, который полностью перезаписывает старые движения. Соответственно, платформе 1С не требуется хранить отдельный постоянный GUID для каждой отдельной строки.
Если внешняя система не требует строгого формата UUID (36 символов с дефисами), самым надежным и быстрым вариантом будет формирование ключа из системных полей платформы: GUID регистратора и номера строки.
Посмотрим на пример формирования такого ключа при обходе выборки регистра:
Выборка = РегистрыНакопления.Продажи.Выбрать();
Пока Выборка.Следующий() Цикл
// Получаем строковый GUID регистратора и номер строки
ГуидРегистратора = Строка(Выборка.Регистратор.УникальныйИдентификатор());
НомерЗаписи = Формат(Выборка.НомерСтроки, "ЧГ=0");
// Составляем уникальный ключ записи
ИдентификаторСтроки = ГуидРегистратора + "_" + НомерЗаписи;
// Передаем сформированный идентификатор в структуру выгрузки
КонецЦикла;
Такой ключ гарантирует абсолютную уникальность в пределах базы данных, поскольку один и тот же регистратор не может иметь двух записей с одинаковым номером строки.
Часто веб-сервисы, REST API или базы данных на стороне сайта требуют, чтобы идентификатор строго соответствовал стандарту UUID (128 бит в шестнадцатеричном представлении вида xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx). В этом случае мы можем применить хеширование составного ключа алгоритмом MD5.
Разберем по шагам, как получить стабильный UUID на основе данных строки:
Выборка = РегистрыНакопления.Продажи.Выбрать();
Пока Выборка.Следующий() Цикл
СоставнойКлюч = Строка(Выборка.Регистратор.УникальныйИдентификатор()) + "_" + Формат(Выборка.НомерСтроки, "ЧГ=0");
// Получаем 32-символьный хэш MD5
Хеширование = Новый ХешированиеДанных(ХешФункция.MD5);
Хеширование.Добавить(СоставнойКлюч);
ХешСтрока = НРег(Хеширование.ХешСумма);
// Форматируем хэш-строку по маске UUID (8-4-4-4-12)
СтрокаGUID = Сред(ХешСтрока, 1, 8) + "-" +
Сред(ХешСтрока, 9, 4) + "-" +
Сред(ХешСтрока, 13, 4) + "-" +
Сред(ХешСтрока, 17, 4) + "-" +
Сред(ХешСтрока, 21, 12);
ИдентификаторЗаписи = Новый УникальныйИдентификатор(СтрокаGUID);
КонецЦикла;
Этот метод генерирует полностью валидный УникальныйИдентификатор. Главное преимущество такого подхода — детерминированность: при повторной выгрузке одной и той же строки будет получен в точности такой же GUID.
Если перед нами стоит задача однократной передачи данных потоком (например, отправка логов или сообщений в шину данных без необходимости последующего обновления или сопоставления конкретной записи), допустимо генерировать идентификатор динамически с помощью встроенного конструктора 1С:
ИдентификаторЗаписи = Новый УникальныйИдентификатор();
Помните, что при следующем запуске выгрузки данный код сгенерирует абсолютно новое значение, поэтому для синхронизации и обновления ранее выгруженных записей этот вариант не подходит.
Рассмотрим важный нюанс: привязка идентификатора к свойству НомерСтроки имеет уязвимость. Если пользователь откроет документ-регистратор, переместит строки табличной части вверх-вниз или удалит промежуточную строку и перепроведет документ, номера строк движений регистра изменятся. Внешняя база данных в этом случае воспримет старую запись как удаленную, а обновленную — как совершенно новую.
Если в вашей нетиповой конфигурации требуется гарантировать пожизненную неизменность идентификатора движения даже при перепроведении и сортировке строк документа, рекомендуется следующий архитектурный подход:
ИдентификаторСтроки с типом Строка (длина 36) или используйте системное поле.ОбработкаПроведения модуля документа транслируйте этот идентификатор из строки табличной части напрямую в соответствующее поле набора записей регистра накопления.При таком подходе запись регистра будет обладать постоянным неизменяемым GUID на протяжении всего своего жизненного цикла.