В процессе работы с базой данных 1С на уровне SQL Server программисты часто сталкиваются с необходимостью сопоставить записи из таблиц базы данных с объектами в интерфейсе 1С. Основная сложность заключается в том, что в SQL идентификаторы объектов (поля _IDRRef) хранятся в бинарном формате, который отличается по структуре от привычного нам УникальногоИдентификатора (GUID) в 1С. В этой статье мы подробно разберем, как выполнить обратную конвертацию и получить полноценную ссылку.
Для начала проанализируем ситуацию: почему нельзя просто скопировать строку из SQL и вставить её в 1С? Дело в оптимизации. Платформа 1С:Предприятие использует специфический порядок байтов при хранении идентификаторов в MS SQL Server. Это сделано для того, чтобы наиболее часто меняющиеся части GUID находились в конце значения. Для SQL Server это означает более эффективное построение индексов и уменьшение фрагментации таблиц.
Стандартный GUID выглядит как AABBCCDD-EEFF-GGHH-IIJJ-KKLLMMNNOOPP. Однако в поле _IDRRef SQL-таблицы он превращается в 0xIIJJKKLLMMNNOOPPEEFFGGDDAABBCCDD. Как мы видим, блоки байтов меняются местами по определенному алгоритму.
Рассмотрим пример кода, который позволяет преобразовать шестнадцатеричную строку из SQL в понятный платформе УникальныйИдентификатор. Если у вас есть строка вида 0x87CBD485614D5F2411E68BCCE80213E6, мы можем применить следующий метод:
// Предположим, входная строка получена из SQL
IDRref = "0x87CBD485614D5F2411E68BCCE80213E6";
// Убираем префикс 0x, если он есть
ЧистаяСтрока = Сред(IDRref, 3);
// Выполняем перестановку байтов по схеме 1С
// Последние 8 символов (4 байта) + блок 21-24 + блок 17-20 + первые 16 символов
РезультатGUID = НРег(Строка(Прав(ЧистаяСтрока, 8) + "-" +
Сред(ЧистаяСтрока, 21, 4) + "-" +
Сред(ЧистаяСтрока, 17, 4) + "-" +
Лев(ЧистаяСтрока, 4) + "-" +
Сред(ЧистаяСтрока, 5, 12)));
УИД = Новый УникальныйИдентификатор(РезультатGUID);
Разберем, что происходит в этом коде. Мы разбиваем исходную бинарную строку на сегменты и пересобираем их в канонический вид GUID, который ожидает конструктор Новый УникальныйИдентификатор(). Важно помнить, что этот метод работает, если вы точно знаете, к какому типу метаданных относится данная запись.
Выясним, как превратить полученный УникальныйИдентификатор в живую ссылку в информационной базе. Для этого нам понадобится имя объекта метаданных. Например, если мы ищем номенклатуру:
ИмяМетаданных = "Справочник.Номенклатура";
ТекУИД = Новый УникальныйИдентификатор(РезультатGUID);
// Получаем ссылку через менеджер
Ссылка = Справочники.Номенклатура.ПолучитьСсылку(ТекУИД);
// Проверяем, существует ли объект в базе
Если Ссылка.ПолучитьОбъект() = Неопределено Тогда
Сообщить("Объект с таким идентификатором не найден в БД");
КонецЕсли;
Важный момент: метод ПолучитьСсылку() не делает запрос к базе данных. Он просто создает ссылку «в памяти». Чтобы убедиться, что запись реально существует, необходимо попытаться прочитать объект или выполнить запрос к этой ссылке.
Если вам нужно выполнять такие преобразования часто, проанализируем возможности расширения «Инструменты разработчика». В составе этого комплекса есть «Редактор объекта БД», который позволяет вставить HEX-значение напрямую.
Документ.РеализацияТоваровУслуг).0x....Иногда удобнее сразу получить читаемый GUID прямо в консоли запросов SQL (SSMS). Для этого мы можем написать запрос, который переставит байты на лету с помощью функции SUBSTRING. Посмотрим на пример:
SELECT
CAST(
CAST(SUBSTRING(_IDRRef, 13, 4) AS VARBINARY(4)) +
CAST(SUBSTRING(_IDRRef, 11, 2) AS VARBINARY(2)) +
CAST(SUBSTRING(_IDRRef, 9, 2) AS VARBINARY(2)) +
CAST(SUBSTRING(_IDRRef, 1, 8) AS VARBINARY(8))
AS UNIQUEIDENTIFIER) AS GUID_1C
FROM _Reference15 -- Здесь имя вашей таблицы в SQL
В данном запросе мы принудительно пересобираем бинарное значение _IDRRef так, чтобы приведение к типу UNIQUEIDENTIFIER выдало результат, полностью совпадающий с тем, что мы видим в 1С. Это крайне полезно при отладке сложных интеграций или восстановлении данных.
Рассмотрим более сложную ситуацию, когда у нас есть только бинарный идентификатор, но мы не знаем, к какой таблице он относится. В системных таблицах 1С (например, в регистрах сведений с типом «ЛюбаяСсылка») рядом с полем _RRRef (идентификатор) обычно присутствует поле _RTRef (идентификатор типа).
Поле _RTRef содержит числовой код таблицы. Чтобы понять, какой таблице он соответствует, можно воспользоваться функцией 1С:
СтруктураБД = ПолучитьСтруктуруХраненияБазыДанных();
// В этой структуре можно найти соответствие имен таблиц SQL и метаданных 1С
Таким образом, для полной идентификации ссылки из «сырых» данных SQL нам нужно два компонента: _RTRef для определения таблицы (типа объекта) и _IDRRef для поиска конкретной строки в этой таблице.
В завершение разберем обратный процесс. Если нам нужно найти конкретную ссылку в SQL-запросе, мы должны перевести GUID обратно в HEX. Посмотрим на алгоритм:
Ссылка = Справочники.Номенклатура.НайтиПоНаименованию("Товар");
УИД = Ссылка.УникальныйИдентификатор();
СтрокаGUID = СтрЗаменить(Строка(УИД), "-", "");
// Собираем HEX для SQL
HEX_SQL = Сред(СтрокаGUID, 25, 8) +
Сред(СтрокаGUID, 21, 4) +
Сред(СтрокаGUID, 17, 4) +
Лев(СтрокаGUID, 16);
Сообщить("В SQL искать как: 0x" + ВРег(HEX_SQL));
Теперь мы владеем полным инструментарием для миграции данных между SQL и 1С на уровне идентификаторов. Понимая внутреннюю логику хранения байтов, вы сможете легко диагностировать проблемы и писать эффективные запросы к базе данных.