Мы часто сталкиваемся с задачами интеграции, сверки данных между базами или необходимостью поиска объектов по их внутренним идентификаторам (GUID/UUID) — для такой сверки есть утилита сравнения и поиска расхождений данных между базами 1С. Для таких задач часто применяется продвинутая консоль запросов, позволяющая быстро отладить пакетные запросы. Казалось бы, задача тривиальная: получить уникальный идентификатор ссылки прямо в запросе и превратить его в строку для дальнейшего сравнения или выгрузки. Однако, при попытке сделать это "в лоб", мы сталкиваемся с неочевидным поведением платформы.
Чтобы проводить быстрый анализ данных без лишних сложностей, давайте подробно разберем, почему стандартные функции преобразования типов не работают с уникальными идентификаторами внутри языка запросов, и рассмотрим проверенные на практике способы решения этой задачи.
Первое, что приходит в голову разработчику, — использовать оператор ВЫРАЗИТЬ (CAST). Логика подсказывает следующую конструкцию:
ВЫБРАТЬ
ВЫРАЗИТЬ(Док.Ссылка.УникальныйИдентификатор() КАК СТРОКА(36)) КАК УИД_Строка
ИЗ
Документ.РеализацияТоваровУслуг КАК Док
Но выполнив такой запрос, мы с удивлением обнаружим, что поле УИД_Строка либо пустое, либо содержит значение NULL (в зависимости от контекста). Давайте разберемся, почему так происходит.
Оператор ВЫРАЗИТЬ в языке запросов 1С предназначен не для конвертации данных из одного типа в другой (как это делает функция Строка() во встроенном языке), а для приведения типов. Это критически важное различие.
ВЫРАЗИТЬ позволяет отсечь все лишнее и оставить только значения конкретного типа.Уникальный идентификатор на уровне СУБД (SQL Server, PostgreSQL) хранится как бинарные данные (обычно BINARY(16)). Язык запросов 1С, обеспечивая независимость от конкретной СУБД, не предоставляет встроенного механизма трансляции этих бинарных данных в их шестнадцатеричное строковое представление (hex-string) непосредственно в момент выполнения SQL-запроса.
Таким образом, попытка "выразить" уникальный идентификатор как строку обречена на неудачу, так как эти типы данных несовместимы в контексте оператора приведения типов.
Если ваша задача — просто вывести уникальный идентификатор в отчет или удобную консоль запросов для визуального контроля, либо выгрузить его в простой список без дальнейшей обработки внутри этого же запроса, то самым простым решением будет использование функции ПРЕДСТАВЛЕНИЕ — для отладки таких запросов пригодится продвинутая консоль запросов и СК.
Посмотрим, как это выглядит в коде:
ВЫБРАТЬ
// Получаем сам объект типа "УникальныйИдентификатор"
УНИКАЛЬНЫЙИДЕНТИФИКАТОР(МойДокумент.Ссылка) КАК УИД_Поле,
// Получаем его строковое представление
ПРЕДСТАВЛЕНИЕ(УНИКАЛЬНЫЙИДЕНТИФИКАТОР(МойДокумент.Ссылка)) КАК УИД_Строка
ИЗ
Документ.ЗаказКлиента КАК МойДокумент
Важные особенности этого метода:
ПРЕДСТАВЛЕНИЕ, нельзя выполнять операции соединения (JOIN), группировки или условия (ГДЕ) внутри этого же запроса. СУБД не умеет эффективно индексировать и сравнивать такие вычисляемые поля на лету.Это наиболее универсальный и надежный метод, если вам нужно использовать строковый УИД для поиска, интеллектуального сравнения строк или соединения с данными из внешних источников (например, при загрузке данных из Excel/XML, где ID приходят в виде строк).
Алгоритм действий следующий:
УникальныйИдентификатор.ТаблицаЗначений.Строка().Рассмотрим пример кода реализации этого подхода:
// 1. Создаем запрос для получения данных
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Спр.Ссылка) КАК СсылкаУИД,
| Спр.Наименование,
| Спр.Код
|ИЗ
| Справочник.Номенклатура КАК Спр
|ГДЕ
| Спр.ЭтоГруппа = ЛОЖЬ";
// 2. Выгружаем в ТЗ
ТаблицаДанных = Запрос.Выполнить().Выгрузить();
// 3. Подготавливаем колонку для строкового представления
ТаблицаДанных.Колонки.Добавить("УИД_Строка", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(36)));
// 4. Преобразуем данные средствами платформы (на клиенте или сервере приложений)
Для Каждого СтрокаТЗ Из ТаблицаДанных Цикл
// Здесь работает стандартное преобразование 1С, которое недоступно в языке запросов
СтрокаТЗ.УИД_Строка = Строка(СтрокаТЗ.СсылкаУИД);
КонецЦикла;
// Теперь у нас есть ТаблицаДанных, где есть и типизированный УИД, и его строковое представление.
// Мы можем использовать эту таблицу в другом запросе для соединения.
Этот метод требует больше кода, но он гарантирует корректность данных. Если вы столкнулись с падением производительности при таком подходе, рекомендуем изучить методы оптимизации отчетов с набором данных типа «объект».
Если ваша задача лежит в плоскости создания отчетов, то Система Компоновки Данных (СКД) предоставляет элегантное решение без написания кода, особенно если использовать инструменты расширения возможностей СКД для работы на стороне клиента.
В языке запросов СКД действуют те же ограничения, что и в обычном запросе. Однако СКД имеет мощный механизм Вычисляемых полей, которые рассчитываются уже после выполнения основного запроса к базе данных.
Как это настроить:
УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Ссылка) КАК СсылкаУИД.СтрокаУИД.XMLСтрока(СсылкаУИД) или просто Строка(СсылкаУИД).СКД выполнит запрос к СУБД, получит бинарные данные, а затем преобразует их в строку. В редких архитектурных задачах разработчики даже используют две разных схемы в одном отчете СКД, но для простого преобразования идентификатора достаточно базовых настроек вычисляемых полей.
Давайте проанализируем ситуацию, когда вам нужно регулярно выполнять поиск или соединение по строковому представлению УИДа в высоконагруженной системе. Использование способа с выгрузкой в таблицу значений может быть накладным по ресурсам памяти и времени.
В таких случаях профессиональным архитектурным решением считается добавление специального реквизита в объект метаданных.
Реализация:
ИдентификаторСтрокой (Тип: Строка, Длина: 36, Фиксированная: Да).ПередЗаписью добавляем код:
Если ЭтоНовый() Или ОбменДанными.Загрузка Тогда
Если ПустаяСтрока(ИдентификаторСтрокой) Тогда
СсылкаОбъекта = ?(ЗначениеЗаполнено(Ссылка), Ссылка, УникальныйИдентификатор);
Если ЭтоНовый() Тогда
ИдентификаторСтрокой = Строка(ЭтотОбъект.Ссылка.УникальныйИдентификатор());
Иначе
ИдентификаторСтрокой = Строка(Ссылка.УникальныйИдентификатор());
КонецЕсли;
КонецЕсли;
КонецЕсли;
Такой подход позволяет в будущем делать прямые запросы с условиями вида ГДЕ Док.ИдентификаторСтрокой = &НужнаяСтрока, что будет работать мгновенно благодаря индексам СУБД.
Подводя итог, можно сказать, что получить строку из уникального идентификатора непосредственно внутри запроса 1С для логических операций невозможно из-за ограничений трансляции типов в СУБД. Однако мы рассмотрели три надежных способа решения:
ПРЕДСТАВЛЕНИЕ() — для простого вывода и просмотра.ТаблицаЗначений — для сложных алгоритмов и соединений.