Ссылка на объект 1С:Предприятия изнутри: из чего она состоит, когда появляется и как с ней работать в коде
Содержание
Ссылка на объект в 1С 8.3 формируется из двух частей: типа объекта (например, СправочникСсылка.Номенклатура) и 128-битного уникального идентификатора (UUID). Идентификатор платформа генерирует один раз — при первой записи объекта или заранее, если разработчик задал его сам. После этого ссылка не меняется никогда: ни при переименовании, ни при смене кода и номера, ни при переносе базы.
Типичная ситуация: программист выгружает номенклатуру в интернет-магазин по коду, кладовщик перенумеровывает справочник — и связи рвутся. Если бы обмен шёл по уникальному идентификатору ссылки, ничего бы не случилось. Отсюда и практический смысл темы: понимать, как устроена ссылка, — значит знать, по чему надёжно связывать данные.
Из чего состоит ссылка на объект
Ссылочные типы в 1С — это справочники, документы, планы видов характеристик, планы счетов, планы видов расчёта, бизнес-процессы, задачи, планы обмена и перечисления. Значение любого из этих типов — ссылка.
Ссылка хранит:
- 🔹 тип — какому объекту метаданных она принадлежит;
- 🔹 уникальный идентификатор — 16 байт, в строковом виде 36 символов вида
a1b2c3d4-e5f6-11e9-80c9-000c29c3b2f4.
Код, наименование, номер и дата в ссылку не входят. Это обычные реквизиты, их можно менять сколько угодно. Ссылка же — «паспорт» строки в таблице объекта.
Как ссылка лежит в базе данных
В клиент-серверной базе каждому ссылочному объекту соответствует таблица СУБД с именем вида _Reference123 (справочники), _Document45 (документы) и т. п. Ключевое поле — _IDRRef типа binary(16). Это и есть идентификатор ссылки.
Если реквизит ссылается на один конкретный тип, в таблице хранится только 16 байт. Если тип составной (например, Регистратор регистра или реквизит «Документ-основание»), полей больше:
| Поле в СУБД | Что хранит |
|---|---|
_..._TYPE | признак «что внутри»: ссылка, число, строка, дата |
_..._RTRef | номер ссылочного типа, 4 байта |
_..._RRRef | сам идентификатор, 16 байт |
Соответствие имён таблиц и объектов метаданных возвращает функция ПолучитьСтруктуруХраненияБазыДанных(). Её удобно вызвать из консоли или обработки, если нужно найти таблицу по имени справочника.
Не меняйте данные в таблицах 1С напрямую через SQL. Платформа не узнает об изменениях: не обновятся итоги, кэш, регистрации в планах обмена. Чтение для анализа допустимо, запись — нет.
Постоянная ссылка и ссылка нового объекта
Пока объект не записан, ссылки у него нет. Создаёте Справочники.Номенклатура.СоздатьЭлемент() — у объекта Ссылка.Пустая() вернёт Истина. Идентификатор появится в момент Записать().
Отсюда три состояния:
| Состояние | Что в Ссылка | Где встречается |
|---|---|---|
| Пустая ссылка | UUID из нулей 00000000-0000-0000-0000-000000000000 | незаполненный реквизит, новый объект до записи |
| Ссылка нового | идентификатор задан заранее, но объект ещё не записан | УстановитьСсылкуНового(), загрузка из обмена |
| Постоянная ссылка | идентификатор записанного объекта | обычная работа |
Ссылка нового объекта
Иногда ссылку нужно знать до записи. Например, документ и присоединённые файлы создаются в одной транзакции, и файлу надо сразу указать владельца. Для этого есть два метода объекта:
НовыйДокумент = Документы.ПоступлениеТоваровУслуг.СоздатьДокумент();
// Вариант 1: получить идентификатор, который присвоят при записи
СсылкаНового = НовыйДокумент.ПолучитьСсылкуНового();
Если СсылкаНового.Пустая() Тогда
СсылкаНового = Документы.ПоступлениеТоваровУслуг.ПолучитьСсылку();
НовыйДокумент.УстановитьСсылкуНового(СсылкаНового);
КонецЕсли;
// Вариант 2: задать известный идентификатор (например, из внешней системы)
УИД = Новый УникальныйИдентификатор("a1b2c3d4-e5f6-11e9-80c9-000c29c3b2f4");
НовыйДокумент.УстановитьСсылкуНового(Документы.ПоступлениеТоваровУслуг.ПолучитьСсылку(УИД));
ПолучитьСсылкуНового() возвращает пустую ссылку, если ссылка нового не устанавливалась. Поэтому в примере сначала генерируем ссылку через менеджер, потом назначаем её объекту.
В обработчике формы нового объекта признак «объект ещё не записан» проверяют так: Объект.Ссылка.Пустая(). Это надёжнее, чем смотреть на пустой код или номер — их могут заполнить до записи.
Навигационная ссылка
Пользователи часто называют «ссылкой» строку, которую копируют через Ctrl+F11 или из меню формы, — например e1cib/data/Справочник.Номенклатура?ref=80c9000c29c3b2f411e9e5f6a1b2c3d4. Это навигационная ссылка: адрес для открытия объекта в интерфейсе. В коде её возвращает ПолучитьНавигационнуюСсылку(Ссылка).
После ref= стоят те же 16 байт идентификатора, но в порядке хранения в СУБД, без дефисов. Об этом порядке — в следующем разделе.
Как платформа генерирует уникальный идентификатор
Платформа использует UUID, основанный на времени (версия 1 по стандарту RFC 4122). Его признак виден в строке: третья группа начинается с цифры 1 — ...-11e9-..., ...-11ee-.... В идентификатор входят метка времени и данные узла, поэтому совпадение двух UUID на практике исключено, даже если объекты создают тысячи пользователей одновременно.
Почему в SQL идентификатор выглядит «перевёрнутым»
Строка UUID состоит из пяти групп: a1b2c3d4-e5f6-11e9-80c9-000c29c3b2f4. В поле _IDRRef платформа пишет их в другом порядке — сначала четвёртая и пятая группы, затем третья, вторая и первая:
Строка UUID: a1b2c3d4-e5f6-11e9-80c9-000c29c3b2f4
В _IDRRef: 0x 80C9 000C29C3B2F4 11E9 E5F6 A1B2C3D4
Смысл перестановки — старшие разряды метки времени оказываются в начале, и новые записи ложатся в индекс ближе к концу, а не в случайные места. Это уменьшает фрагментацию кластерного индекса.
Практическое следствие: чтобы найти в SQL запись по UUID из 1С, переставьте группы по этой схеме. Так же собирают идентификатор из навигационной ссылки обратно в UUID.
Где взять и как восстановить ссылку по UUID
| Задача | Как сделать |
|---|---|
| Получить UUID из ссылки | Ссылка.УникальныйИдентификатор() |
| UUID в строку | Строка(Ссылка.УникальныйИдентификатор()) или XMLСтрока(Ссылка) |
| Ссылка по UUID | Справочники.Имя.ПолучитьСсылку(Новый УникальныйИдентификатор(Строка)) |
| Ссылка по строке с указанием типа | XMLЗначение(Тип("СправочникСсылка.Имя"), Строка) |
| Новый случайный UUID | Новый УникальныйИдентификатор() |
ПолучитьСсылку() не проверяет, есть ли объект в базе. Он просто собирает ссылку из типа и идентификатора. Есть ли объект, проверяют запросом или через Ссылка.ПолучитьОбъект() — он вернёт Неопределено, если записи нет.
Работа со ссылками в запросах и коде
В запросах
Ссылка в запросе — обычное поле, по которому сравнивают и соединяют. Полезные конструкции:
- 🔍
ЗНАЧЕНИЕ(Справочник.Валюты.ПустаяСсылка)— сравнение с пустой ссылкой без параметра; - 🔍
Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг— проверка типа ссылки в составном поле; - 🔍
ВЫРАЗИТЬ(Регистратор КАК Документ.РеализацияТоваровУслуг).Договор— обращение к реквизиту конкретного типа; - 🔍
ПРЕДСТАВЛЕНИЕ(Номенклатура)— текст ссылки для вывода, без лишнего соединения в отчёте.
Обращение через точку (Номенклатура.ЕдиницаИзмерения.Наименование) платформа превращает в неявное левое соединение с таблицей объекта. Для поля составного типа соединение строится со всеми таблицами, которые входят в тип. Поле Регистратор у регистра, куда пишут 30 видов документов, даст 30 соединений.
Если обращаетесь через точку к составному полю, сначала приведите его через ВЫРАЗИТЬ к нужному типу. Запрос станет в разы легче.
В коде
- ✅ Ссылки сравнивают напрямую:
Если Строка.Контрагент = Документ.Контрагент Тогда. Сравнивается тип и идентификатор. - ✅ Пустоту проверяют методом
Пустая()или сравнением сСправочники.Имя.ПустаяСсылка(). - ✅ Значение реквизита по ссылке в типовых конфигурациях на БСП удобно брать через
ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ссылка, "ИмяРеквизита")— это один запрос, а не чтение всего объекта. - ❌ Не храните ссылку как наименование или код в строковом реквизите — при переименовании связь потеряется.
- ❌ Не обращайтесь через точку к ссылке в цикле по большой выборке: каждое
Ссылка.Реквизитна сервере читает данные объекта. Получите нужные поля в запросе.
Для сохранения ссылки во внешнем файле или параметре используйте UUID плюс имя типа. Функция ЗначениеВСтрокуВнутр() тоже сохраняет ссылку, но её формат внутренний и зависит от структуры конфигурации — для обмена с другими системами он не годится.
Ссылки в распределённых базах и обменах
Уникальность UUID — главная причина, по которой распределённая информационная база (РИБ) работает без конфликтов идентификаторов. Узлы создают объекты независимо, и ссылки не пересекаются. А вот коды и номера пересечься могут, поэтому в РИБ каждому узлу задают свой префикс.
Как передаётся ссылка между базами:
- 🔗 РИБ. Объект приходит в другой узел с тем же идентификатором. Ссылка в главном и подчинённом узле одна и та же.
- 🔗 Обмен через XML-сериализацию (
ЗаписатьXML, планы обмена). В сообщении ссылка — элементRefс UUID. При загрузке платформа ищет объект по этому идентификатору; если не нашла, создаёт новый с той же ссылкой. - 🔗 Обмен через правила конвертации (EnterpriseData и др.). Ссылки в разных конфигурациях могут не совпадать. Объекты сопоставляются по UUID, а при неудаче — по полям поиска (ИНН, код, наименование). Соответствия идентификаторов разных баз типовые конфигурации хранят в отдельном регистре сведений подсистемы обмена.
Откуда берутся битые ссылки
Если в базу пришёл документ, а контрагент, на которого он ссылается, ещё не выгружен, реквизит получит ссылку на несуществующий объект. В форме вместо названия появится строка вида:
<Объект не найден> (123:80c9000c29c3b2f411e9e5f6a1b2c3d4)
Число до двоеточия — номер ссылочного типа (тот же, что в имени таблицы _Reference123). После двоеточия — идентификатор в порядке хранения СУБД. По этим двум значениям можно найти, на какой справочник ссылка и какой объект потерялся.
Битые ссылки появляются и без обменов:
- ⚡ объект удалили непосредственно, минуя пометку на удаление и проверку ссылок;
- ⚡ загрузили часть данных из другой базы через универсальную выгрузку;
- ⚡ запись в таблицу изменили SQL-скриптом.
Ошибки при работе со ссылками и как их исправить
Массовая проверка ссылочной целостности
В конфигураторе откройте Администрирование → Тестирование и исправление, отметьте «Проверка логической целостности» и «Проверка ссылочной целостности». Для найденных битых ссылок есть три варианта: создавать объекты, очищать ссылки или не изменять.
- «Создавать объекты» — платформа создаст пустые элементы-заглушки с потерянными идентификаторами. Связи сохранятся, а данные заглушек потом можно дозаполнить или подтянуть повторным обменом.
- «Очищать ссылки» — реквизиты станут пустыми. Восстановить, на что ссылался документ, будет уже нельзя.
Тестирование с исправлением требует монопольного доступа: попросите пользователей выйти и запускайте во внерабочее время. Сделайте резервную копию базы перед запуском — «очистку ссылок» не отменить.
Начинайте с режима «не изменять»: он только покажет, сколько битых ссылок и где. Решение о «создании» или «очистке» принимайте после просмотра списка.
Частые вопросы
Можно ли изменить ссылку у существующего объекта?
УстановитьСсылкуНового() ссылкой и перенесите связи обработкой поиска и замены ссылок.Совпадает ли ссылка в копии базы и в файле .dt?
Сколько весит ссылка в базе?
Почему у перечисления тоже есть ссылка?
Перечисления.Имя.Значение или ЗНАЧЕНИЕ() в запросе.Чем ссылка отличается от навигационной ссылки?
e1cib/... для открытия объекта в интерфейсе; её можно отправить коллеге, и у него откроется та же карточка.