Идентификатор объекта в 1С: GUID, ссылка и УникальныйИдентификатор
Содержание
Идентификатор объекта в 1С — это его GUID, 36-символьная строка вида e1f2a3b4-1234-5678-9abc-def012345678. Получить его из любой ссылки на справочник, документ или другой объект можно одной строкой: Ид = Ссылка.УникальныйИдентификатор(). Метод возвращает значение типа УникальныйИдентификатор, а в читаемую строку оно переводится через Строка(Ид).
Дальше разберём обратную задачу — получить ссылку по известному GUID, назначить идентификатор новому объекту до записи, выбрать идентификаторы пачкой запросом, сгенерировать случайные GUID для тестов и перевести значение между строкой, объектом и ссылкой. Весь код — на встроенном языке 1С 8.3, платформа «Такси».
Чем ссылка отличается от УникальногоИдентификатора
Это два разных типа, и путаница между ними — источник большинства ошибок.
🔗 Ссылка (
СправочникСсылка.Контрагенты,ДокументСсылка.РеализацияТоваровУслуг) — это указатель на объект вместе с его типом. По ссылке можно прочитать реквизиты, получить объект, подставить в реквизит документа.🆔 УникальныйИдентификатор — только GUID, без типа. Сам по себе он не знает, к какому справочнику относится.
🌐 Навигационная ссылка — ещё одно «имя» объекта, строка
e1cib/data/.... Это адрес для гиперссылок внутри интерфейса, в неё GUID входит как часть. Путать её с чистым идентификатором не стоит.
Отсюда главное правило: по одному GUID восстановить ссылку нельзя — нужно ещё знать тип объекта. Поэтому идентификатор почти всегда хранят в паре с именем таблицы (например, Справочник.Контрагенты).
Физически в СУБД GUID лежит в бинарном поле _IDRRef. Напрямую к таблицам базы данных обращаться не нужно и опасно — платформа даёт всё необходимое через встроенный язык. Идентификатор присваивается один раз при создании объекта и после записи не меняется: на нём держатся все ссылки между объектами, движения регистров и записи обменов. Именно поэтому GUID, а не код или наименование, служит ключом сопоставления при переносе данных между базами.
Получаем идентификатор у существующего объекта
Если на руках уже есть ссылка, идентификатор берётся методом УникальныйИдентификатор():
Ид = ВашаСсылка.УникальныйИдентификатор(); // тип УникальныйИдентификатор
СтрокаИд = Строка(Ид); // "e1f2a3b4-1234-5678-9abc-def012345678"
Сообщить(СтрокаИд);
Метод работает для любого ссылочного типа: элементов справочников, документов, планов видов характеристик, счетов и так далее. У пустой ссылки (Справочники.Контрагенты.ПустаяСсылка()) идентификатор будет нулевым: 00000000-0000-0000-0000-000000000000.
Из формы объекта ссылку берут из реквизита Объект.Ссылка. На управляемой форме это выглядит так:
&НаКлиенте
Процедура ПоказатьИдентификатор(Команда)
Сообщить(Строка(Объект.Ссылка.УникальныйИдентификатор()));
КонецПроцедуры
Для только что созданного и ещё не записанного элемента Объект.Ссылка будет пустой — идентификатор появится после первой записи, если его не назначили вручную (см. раздел ниже).
Если нужно пройтись по нескольким объектам, ссылку удобно получить из выборки, а GUID вытащить уже в коде:
Запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура");
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Ид = Выборка.Ссылка.УникальныйИдентификатор();
// ... дальше работаем с Ид
КонецЦикла;
В интерактивном режиме, без кода, штатной кнопки «показать GUID» нет. Но команда Ещё → Получить ссылку в форме объекта выдаёт навигационную ссылку вида e1cib/data/Справочник.Номенклатура?ref=..., где после ref= стоит тот же идентификатор в сжатом виде.
Назначаем идентификатор новому объекту до записи
Обычно при записи платформа сама присваивает новому объекту случайный GUID. Задавать идентификатор вручную нужно только в особых случаях: когда ссылка требуется до записи (например, два объекта ссылаются друг на друга) или когда идентификатор приходит из внешней системы.
Порядок такой:
- Сгенерировать или получить
УникальныйИдентификатор. - Построить ссылку через менеджер объекта.
- Привязать её к новому объекту методом
УстановитьСсылкуНового. - Записать объект.
НовыйИд = Новый УникальныйИдентификатор(); // случайный GUID
НоваяСсылка = Справочники.Контрагенты.ПолучитьСсылку(НовыйИд);
Объект = Справочники.Контрагенты.СоздатьЭлемент();
Объект.УстановитьСсылкуНового(НоваяСсылка);
Объект.Наименование = "ООО Ромашка";
Объект.Записать();
УстановитьСсылкуНового сработает только на новом, ещё не записанном объекте. Для уже существующего объекта сменить идентификатор штатно нельзя.
Типичный случай, когда без этого не обойтись, — взаимные ссылки. Например, элемент справочника должен в одном из реквизитов ссылаться сам на себя или на «соседний» объект, который создаётся в той же процедуре. Записать такой объект «вслепую» не выйдет: реквизит требует готовую ссылку, а она появляется только после записи. Выход — заранее получить ссылку через ПолучитьСсылку, проставить её в реквизиты обоих объектов и лишь затем записать их. Без предварительного назначения идентификатора пришлось бы записывать объект дважды: сначала пустым, потом с заполненной ссылкой.
Как получить ссылку обратно по GUID
Обратная операция — построить ссылку из известного идентификатора. Делается методом менеджера ПолучитьСсылку, которому передают объект УникальныйИдентификатор:
Ид = Новый УникальныйИдентификатор("e1f2a3b4-1234-5678-9abc-def012345678");
Ссылка = Справочники.Контрагенты.ПолучитьСсылку(Ид);
Здесь и всплывает различие из первого раздела: менеджер (Справочники.Контрагенты) задаёт тип, а GUID — конкретный экземпляр. Без правильного менеджера ссылку не собрать.
Важная деталь: ПолучитьСсылку не проверяет, существует ли объект в базе. Он вернёт формально корректную ссылку, даже если такого элемента нет или он помечен и удалён физически. Проверить фактическое наличие можно так:
Если Ссылка.ПолучитьОбъект() = Неопределено Тогда
Сообщить("Объекта с таким идентификатором в базе нет");
КонецЕсли;
ПолучитьОбъект() возвращает Неопределено, если за ссылкой нет реальной записи, — это надёжнее, чем читать реквизиты вслепую.
А что делать, если тип объекта заранее неизвестен — на руках только строка GUID? Единственный честный способ — перебрать кандидатов. Идентификатор хранят вместе с именем таблицы, и тогда менеджер получают по строке типа:
ПолноеИмя = "Справочник.Контрагенты"; // хранится рядом с GUID
Менеджер = Тип(ПолноеИмя); // для динамики — через метаданные
На практике проще сразу сохранять идентификатор в формате Справочник.Контрагенты:e1f2a3b4-...: по левой части берут менеджер, по правой — GUID. Перебирать все справочники базы в поисках «чьего» это идентификатора — медленно и ненадёжно, так делать не стоит.
Извлечение идентификаторов пачкой через запрос
Частая задача — выгрузить идентификаторы всех объектов выборки (для обмена, сверки, журнала соответствий). В языке запросов 1С нет функции, которая вернула бы GUID прямо в колонку результата. Поэтому схема всегда двухшаговая: запросом получаем ссылки, а идентификаторы снимаем в цикле уже кодом.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ Ссылка, Наименование
|ИЗ Справочник.Номенклатура
|ГДЕ НЕ ПометкаУдаления";
Выборка = Запрос.Выполнить().Выбрать();
Соответствие = Новый Соответствие; // GUID -> наименование
Пока Выборка.Следующий() Цикл
Ключ = Строка(Выборка.Ссылка.УникальныйИдентификатор());
Соответствие.Вставить(Ключ, Выборка.Наименование);
КонецЦикла;
Не пытайтесь читать GUID напрямую из таблиц СУБД (поля _IDRRef, _Reference). Их структура не документирована, зависит от релиза платформы и типа базы, а любое прямое изменение ломает базу. Всё, что нужно, доступно через УникальныйИдентификатор().
Двухшаговая схема не замедляет работу: УникальныйИдентификатор() просто читает уже загруженное значение ссылки, обращения к базе здесь нет. Поэтому цикл по выборке в тысячи строк отрабатывает быстро, а результат сразу складывается в удобную структуру — Соответствие, ТаблицуЗначений или строку обмена.
Для отбора по идентификатору в самом запросе удобнее передать уже готовую ссылку параметром:
Запрос.УстановитьПараметр("Ссылка", ВашаСсылка);
// в тексте запроса: ГДЕ Ссылка = &Ссылка
Генерация случайных идентификаторов для тестов и временных ключей
Отдельный УникальныйИдентификатор можно создать без всякого объекта — конструктором Новый:
Для Счётчик = 1 По 5 Цикл
Сообщить(Строка(Новый УникальныйИдентификатор()));
КонецЦикла;
Каждый вызов даёт новый случайный GUID. Вероятность совпадения двух таких значений настолько мала, что на практике её не учитывают. Где это пригождается:
- 🧪 Тесты — подставить заведомо несуществующий идентификатор и проверить реакцию кода.
- 🔑 Временные ключи — уникальное имя элемента в
СоответствииилиТаблицеЗначений, когда осмысленного ключа нет. - 🔁 Идемпотентность обменов — пометить сообщение, чтобы не обработать его дважды.
- 📄 Имена временных файлов — уникальный суффикс, чтобы два процесса не затёрли файл друг друга.
Случайный GUID не возрастает по порядку и не связан со временем создания. Сортировать по нему или выводить из него дату бессмысленно — для этого есть отдельные реквизиты.
Сгенерированный таким образом идентификатор сам по себе ни к чему не привязан: пока вы не передали его в ПолучитьСсылку и не записали объект, это просто уникальное значение. Удобно заранее создать GUID, записать его в журнал обмена или во внешнюю систему, а объект в 1С создать позже — связь между системами сохранится, потому что обе стороны знают один и тот же идентификатор. Это стандартный приём при двусторонних интеграциях, когда порядок создания объектов в разных базах не гарантирован.
Конвертация: строка, УникальныйИдентификатор и ссылка
Три представления одного идентификатора переводятся друг в друга стандартными средствами. Сводка:
| Что есть | Что нужно | Как получить |
|---|---|---|
| строка | УникальныйИдентификатор | Новый УникальныйИдентификатор(Стр) |
| УникальныйИдентификатор | строка | Строка(Ид) или XMLСтрока(Ид) |
| строка | ссылка | Менеджер.ПолучитьСсылку(Новый УникальныйИдентификатор(Стр)) |
| ссылка | УникальныйИдентификатор | Ссылка.УникальныйИдентификатор() |
| ссылка | навигационная ссылка | ПолучитьНавигационнуюСсылку(Ссылка) |
Пример полного цикла строка → ссылка → строка:
СтрокаGUID = "e1f2a3b4-1234-5678-9abc-def012345678";
Ид = Новый УникальныйИдентификатор(СтрокаGUID);
Ссылка = Документы.РеализацияТоваровУслуг.ПолучитьСсылку(Ид);
Проверка = Строка(Ссылка.УникальныйИдентификатор()); // снова СтрокаGUID
Конструктор Новый УникальныйИдентификатор(Стр) требует ровно 36 символов канонического формата с дефисами. Строка другой длины или с лишними символами вызовет ошибку выполнения. Если источник данных ненадёжный, проверяйте длину или оборачивайте вызов в Попытка … Исключение.
Когда идентификатор приходит из внешнего обмена, строку из ненадёжного источника удобно разбирать через механизм сериализации:
Попытка
Ид = XMLЗначение(Тип("УникальныйИдентификатор"), СтрокаИзОбмена);
Исключение
// некорректный формат — логируем и пропускаем
ЗаписьЖурналаРегистрации("Обмен", УровеньЖурналаРегистрации.Ошибка,
, , "Неверный GUID: " + СтрокаИзОбмена);
Возврат;
КонецПопытки;
Пара XMLСтрока / XMLЗначение удобна тем, что это тот же формат, в котором идентификаторы ездят в XML-обменах и планах обмена, — вы работаете с данными ровно так, как их видит платформа.
Не путайте GUID и навигационную ссылку: ПолучитьНавигационнуюСсылку возвращает длинный внутренний адрес e1cib/data/..., пригодный для гиперссылок внутри интерфейса, а не чистый 36-символьный идентификатор.
Частые ошибки при работе с идентификаторами
- ❌ Хранят GUID без типа. Позже по строке невозможно собрать ссылку — неизвестен менеджер. Сохраняйте идентификатор вместе с именем таблицы.
- ❌ Считают ссылку от
ПолучитьСсылкудоказательством, что объект есть. Метод типа не проверяет базу. Нужна проверка черезПолучитьОбъект() = Неопределено. - ❌ Сравнивают идентификаторы как строки в разном регистре. Надёжнее сравнивать значения типа
УникальныйИдентификаторнапрямую (Ид1 = Ид2), а не их строковые представления. - ❌ Ждут, что
УстановитьСсылкуНовогосменит идентификатор существующего объекта. Он работает только до первой записи. - ❌ Путают навигационную ссылку с GUID. Строка
e1cib/data/...— это адрес, а не идентификатор; передавать её вНовый УникальныйИдентификатор()нельзя.
Частые вопросы
Уникален ли GUID во всей базе или только внутри справочника?
Справочники.Контрагенты и т. п.).Сохраняется ли идентификатор при переносе объекта в другую базу?
Можно ли задать объекту «красивый» идентификатор вручную?
ПолучитьСсылку с нужным GUID и УстановитьСсылкуНового до записи. Но практического смысла почти нет: идентификатор служебный, пользователь его не видит.Как получить GUID объекта в режиме «Предприятие» без программирования?
Ещё → Получить ссылку даёт навигационную ссылку, где идентификатор зашит после ref=. Чистый GUID проще снять небольшой обработкой с методом УникальныйИдентификатор().