Разработка и Конфигурация · 10 мин
Как в запросе получить уникальный идентификатор в 1С 8.3
Как получить уникальный идентификатор ссылки в запросе 1С 8.3: функция УникальныйИдентификатор, значение в запросе, обратное преобразование, типичные ошибки.
Уникальный идентификатор (GUID) — внутренний идентификатор ссылки в 1С, строка из 36 символов вида «8b3f7c2e-1a4d-11e7-9f2a-00155d0a1b02». Он нужен при обмене данными между базами, при интеграции с внешними системами и при поиске «потерянных» объектов. Проблема в том, что в языке запросов 1С нет прямой функции, возвращающей GUID ссылки: конструкция Ссылка.УникальныйИдентификатор() в тексте запроса недоступна и вызовет ошибку.
На практике задачу решают тремя рабочими способами: получают GUID уже после выполнения запроса при обходе выборки, передают готовый GUID параметром в запрос через значение ссылки или используют строковое представление ссылки для обратного поиска. Ниже разобран каждый вариант с кодом, ограничениями и типичными ошибками, а также обратная операция — получение ссылки по известному GUID.
Почему GUID нельзя получить прямо в тексте запроса
Язык запросов 1С работает на уровне СУБД и оперирует полями таблиц, а не объектами встроенного языка. Метод УникальныйИдентификатор() принадлежит объектному уровню — он вызывается у значения типа «ссылка» уже после того, как платформа материализовала результат. Поэтому конструкция вида ВЫБРАТЬ Товары.Ссылка.УникальныйИдентификатор() синтаксически невозможна: запрос просто не скомпилируется.
Также нельзя вывести GUID через функцию ПРЕДСТАВЛЕНИЕ() — она вернёт наименование или другое представление объекта, а не идентификатор. Внутреннее двоичное представление ссылки в таблице СУБД тоже не предназначено для чтения запросом и зависит от формата хранения, поэтому любые «хаки» с прямым обращением к служебным полям нестабильны и не поддерживаются платформой.
Из этого следует главное правило: запрос возвращает ссылку, а GUID извлекается на уровне встроенного языка — либо в цикле обхода выборки, либо через СКД с вычисляемым полем, либо GUID передаётся в запрос извне как параметр.
Способ 1: получение GUID при обходе результата запроса
Самый распространённый сценарий: запрос выбирает ссылки, а GUID вычисляется в цикле. Это быстро, потому что ссылка уже получена запросом, и метод УникальныйИдентификатор() не выполняет дополнительных обращений к базе.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Наименование КАК Наименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| НЕ Номенклатура.ПометкаУдаления";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
GUID = XMLСтрока(Выборка.Ссылка);
// или: GUID = Строка(Выборка.Ссылка.УникальныйИдентификатор());
КонецЦикла;
Обе формы — XMLСтрока(Ссылка) и Строка(Ссылка.УникальныйИдентификатор()) — дают одинаковый строковый GUID. Вариант с XMLСтрока() предпочтительнее в универсальном коде: функция корректно работает с любой ссылкой без явного вызова метода и широко используется в типовых механизмах обмена.
Если результат нужно выгрузить в таблицу значений с колонкой GUID, заполните её постобработкой: добавьте колонку типа «Строка(36)» и заполните в цикле обхода. Это честнее и прозрачнее, чем попытки «вытащить» идентификатор внутри запроса.
Способ 2: передать GUID в запрос параметром (поиск ссылки по GUID)
Обратная задача встречается чаще: из внешней системы пришёл GUID, и нужно найти объект. Здесь запрос используется как раз напрямую — сначала GUID преобразуется в ссылку, затем ссылка передаётся параметром.
СтрокаGUID = "8b3f7c2e-1a4d-11e7-9f2a-00155d0a1b02";
НовыйGUID = Новый УникальныйИдентификатор(СтрокаGUID);
СсылкаНаТовар = Справочники.Номенклатура.ПолучитьСсылку(НовыйGUID);
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Наименование КАК Наименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", СсылкаНаТовар);
Результат = Запрос.Выполнить();
Важная проверка: ПолучитьСсылку() возвращает ссылку даже если объекта с таким GUID в базе нет. Поэтому результат запроса нужно контролировать — если выборка пустая, значит объект отсутствует (удалён физически или GUID из другой базы). Альтернативная проверка без запроса: СсылкаНаТовар.ПолучитьОбъект() вернёт Неопределено для несуществующего объекта.
Также полезна функция Справочники.Номенклатура.ПустаяСсылка() для сравнения: полученная ссылка на несуществующий объект пустой не является, поэтому полагаться на сравнение с пустой ссылкой нельзя — только на фактическое наличие записи в базе.
Способ 3: GUID в отчёте на СКД через вычисляемое поле
Если GUID нужно показать пользователю в отчёте, используют вычисляемое поле СКД с выражением на встроенном языке. В настройках набора данных добавьте вычисляемое поле, например «GUID», и в выражении укажите вызов функции из общего модуля:
// В общем серверном модуле с флагом "Вызов сервера"
Функция GUIDСсылки(Ссылка) Экспорт
Возврат XMLСтрока(Ссылка);
КонецФункции
// Выражение вычисляемого поля СКД:
// ОбщийМодуль.GUIDСсылки(Ссылка)
Модуль должен быть серверным и с разрешённым вызовом сервера, иначе выражение не скомпилируется. Учтите, что вычисляемые поля с вызовом функций замедляют формирование больших отчётов — функция вызывается для каждой строки результата.
Сравнение способов и выбор подходящего
Сравнение вариантов
Универсальный и самый быстрый способ получить GUID для списка объектов. Подходит для выгрузок и обменов. Ограничение: GUID доступен только в коде, не в тексте запроса.
Единственный корректный путь, когда нужен отбор по известному GUID. Требует знать тип объекта заранее.
Подходит для отчётов, где GUID должен видеть пользователь. Минус — вызов функции на каждую строку и требования к общему модулю.
Выбор определяется направлением задачи. Если GUID нужно получить — работайте после запроса. Если по GUID нужно найти объект — преобразуйте GUID в ссылку до запроса и передайте параметром. Если объект неизвестного типа, переберите менеджеры нужных видов объектов или используйте XMLЗначение() совместно с типом, переданным из внешней системы.
Частые ошибки при работе с GUID в запросах
Отдельно отметим несуществующие («битые») ссылки. Если в поле запроса оказалась ссылка на удалённый объект, УникальныйИдентификатор() у неё вызвать можно, но любое обращение к реквизитам через точку в запросе даст NULL. Для диагностики таких случаев проверяйте поля на ЕСТЬ NULL и отдельно обрабатывайте эти строки.
Проверка результата
Как проверить результат
Строка из 36 символов: 8-4-4-4-12 шестнадцатеричных знаков через дефисы
Наименование объекта, пустая строка или значение вида «Объект не найден»
Запрос вернул ровно одну строку с нужным объектом
Пустой результат — объекта нет, либо GUID от другого типа объекта
XMLЗначение/ПолучитьСсылку дают ссылку, у которой ПолучитьОбъект() не равен Неопределено
ПолучитьОбъект() вернул Неопределено — объект физически отсутствует
Быстрая ручная проверка в консоли кода: выполните Сообщить(XMLСтрока(Ссылка)) для известного объекта и сравните со значением, которое возвращает ваша процедура. Значения должны совпадать посимвольно, регистр букв при этом не влияет на корректность преобразования обратно.
Что важно запомнить
В языке запросов 1С функции для GUID нет: получайте идентификатор при обходе результата через XMLСтрока(Ссылка), а для поиска по GUID преобразуйте строку в УникальныйИдентификатор, получите ссылку через ПолучитьСсылку() и передайте её параметром. Всегда проверяйте существование объекта после обратного преобразования.
Частые вопросы
Можно ли отфильтровать запрос по части GUID, например по первым символам?
Нет. Ссылка в запросе — не строка, к ней неприменимы строковые функции и оператор ПОДОБНО. Отбор возможен только по полному равенству ссылки, которую предварительно получают из GUID.
Чем XMLСтрока(Ссылка) отличается от Строка(Ссылка.УникальныйИдентификатор())?
Результат идентичен — строковое представление GUID. XMLСтрока удобнее в универсальном коде, так как работает с любой ссылкой единообразно и используется в механизмах сериализации платформы.
Как найти объект по GUID, если неизвестен его тип?
Переберите менеджеры предполагаемых видов объектов (справочники, документы) и для каждого вызовите ПолучитьСсылку() с проверкой существования через ПолучитьОбъект(). Универсального поиска по всем типам одним вызовом в платформе нет.
Сохраняется ли GUID объекта при обмене между базами?
Да, при штатных обменах (план обмена, универсальный формат) GUID переносится вместе с объектом и остаётся одинаковым в обеих базах. Именно поэтому GUID — основной ключ сопоставления при интеграциях.
Почему запрос с условием Ссылка = &GUID, где параметр — строка, ничего не возвращает?
Потому что строка и ссылка — разные типы, сравнение некорректно. Строку нужно сначала преобразовать: Новый УникальныйИдентификатор(Строка), затем получить ссылку через ПолучитьСсылку() и передать в параметр уже ссылку.
Можно ли получить GUID в консоли запросов без написания кода?
Нет, консоль запросов работает только языком запросов, где GUID недоступен. Используйте консоль кода: выберите ссылку запросом и выведите XMLСтрока(Ссылка) в цикле обхода.