При интеграции 1С:Предприятия со сторонними информационными системами (веб-сайтами, мобильными приложениями, внешними базами данных или BI-системами) разработчики часто сталкиваются с необходимостью сопоставления данных. Особый интерес вызывают перечисления. Физически в таблицах СУБД ссылки на перечисления хранятся в виде бинарных данных — 16-байтовых идентификаторов (_IDRRef). В этой статье мы подробно разберем, как устроены перечисления «под капотом» базы данных, и рассмотрим все практические способы получения их уникальных идентификаторов.
Среди начинающих разработчиков существует популярное заблуждение, будто значения перечислений не имеют физических ссылок в СУБД и не являются полноценными объектами базы данных. Это не так. На уровне СУБД для каждого объекта конфигурации типа «Перечисление» создается отдельная полноценная таблица.
Имя таблицы перечисления имеет формат _Enum<n>, где <n> — это порядковый номер объекта в метаданных конфигурации. Каждая такая таблица состоит всего из двух колонок:
binary(16), содержащее уникальный двоичный идентификатор конкретного значения перечисления (его UUID).Когда в справочнике или документе присутствует реквизит с типом «ПеречислениеСсылка», в соответствующей таблице СУБД создается поле _Fld<x>RRef (для простых типов) или набор полей (для составных типов), куда напрямую записывается значение _IDRRef из таблицы перечисления. Таким образом, сопоставление по уникальному идентификатору абсолютно надежно и гарантирует 100% точность.
Самый простой и очевидный способ получить UUID значения перечисления в коде 1С — вызвать стандартный метод УникальныйИдентификатор(). Вопреки старым мифам, значения перечислений являются ссылочным типом данных (ПеречислениеСсылка), поэтому у них есть этот метод.
Рассмотрим пример кода:
ВыбранноеЗначение = Перечисления.ДниНедели.Вторник;
УИД = ВыбранноеЗначение.УникальныйИдентификатор();
Сообщить("Уникальный идентификатор: " + Строка(УИД));
// Выведет стандартную строку UUID: "a73c8a1c-3d84-f454-458a-a55dfb87efd1"
Полученную строку можно напрямую передавать во внешние системы для интеграции.
Отличным и очень быстрым альтернативным решением является использование платформенного механизма сериализации XML. Функция XMLСтрока() принимает ссылку перечисления и возвращает строковое представление его UUID.
Давайте посмотрим на пример реализации:
ЗначениеПеречисления = Перечисления.ДниНедели.Понедельник;
СтрокаUUID = XMLСтрока(ЗначениеПеречисления);
// Результат будет аналогичен методу УникальныйИдентификатор()
Для выполнения обратного преобразования (когда из внешней системы приходит строковый GUID и нужно получить ссылку перечисления в 1С), мы можем использовать парную функцию XMLЗначение():
ИскомыйТип = Тип("ПеречислениеСсылка.ДниНедели");
СсылкаНаЭлемент = XMLЗначение(ИскомыйТип, "a73c8a1c-3d84-f454-458a-a55dfb87efd1");
Иногда при низкоуровневой обработке или сериализации данных программисты используют системную функцию ЗначениеВСтрокуВнутр(). При ее вызове для значения перечисления платформа генерирует строку специального формата:
{"#",de626819-9250-492e-ad27-1776ea2ee050,39:a73c8a1c3d84f454458aa55dfb87efd1}
Проанализируем структуру этой строки:
de626819-9250-492e-ad27-1776ea2ee050) определяет тип метаданных — само перечисление «ДниНедели».39 указывает на внутренний код типа перечисления в платформе.a73c8a1c3d84f454458aa55dfb87efd1) — это шестнадцатеричная строка, представляющая уникальный идентификатор конкретного значения.Обратите внимание, что байты в СУБД и в стандартном UUID формата RFC4122 записываются в разном порядке. Платформа 1С осуществляет побайтовую перестановку (сдвиг подстрок) при преобразовании внутренней строки в стандартный GUID. Если вам требуется сопоставить эту строку напрямую с полем _IDRRef в СУБД, вы можете использовать строковые функции для парсинга и перегруппировки байт.
В современных версиях платформы 1С:Предприятие (начиная с 8.3.27) появилась возможность извлекать уникальный идентификатор прямо внутри запроса. Для этого используется функция УНИКАЛЬНЫЙИДЕНТИФИКАТОР().
Рассмотрим, как это выглядит на практике:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| УНИКАЛЬНЫЙИДЕНТИФИКАТОР(ДниНедели.Ссылка) КАК ГУИДСтрока
|ИЗ
| Перечисление.ДниНедели КАК ДниНедели
|ГДЕ
| ДниНедели.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Перечисления.ДниНедели.Вторник);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Сообщить("Идентификатор из запроса: " + Выборка.ГУИДСтрока);
КонецЕсли;
Этот метод чрезвычайно удобен при формировании сложных отчетов или выгрузок больших объемов данных, так как позволяет избежать циклического обхода и вызова функций платформы для каждой строки.
Если стороннее приложение производит прямую выборку из SQL-таблицы базы данных 1С, сопоставить двоичные идентификаторы _IDRRef со значениями перечислений можно программно на основе порядка следования элементов (индексов).
Разберем этот процесс по шагам:
ПолучитьСтруктуруХраненияБазыДанных() определяем имя таблицы СУБД для интересующего нас перечисления (например, _Enum123).
SELECT _IDRRef, _EnumOrder FROM _Enum123 ORDER BY _EnumOrder
_EnumOrder со значениями 0, 1, 2...) всегда строго соответствует порядку элементов перечисления в конфигураторе (например, Понедельник = 0, Вторник = 1, Среда = 2 и т.д.).Такой подход позволяет один раз кэшировать карту соответствия идентификаторов во внешнем приложении и затем мгновенно сопоставлять любые бинарные поля _IDRRef без обращения к серверу приложений 1С.