Ссылка на объект 1С:Предприятия изнутри: из чего она состоит, когда появляется и как с ней работать в коде

· 9 мин

Содержание

Ссылка на объект в 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 — главная причина, по которой распределённая информационная база (РИБ) работает без конфликтов идентификаторов. Узлы создают объекты независимо, и ссылки не пересекаются. А вот коды и номера пересечься могут, поэтому в РИБ каждому узлу задают свой префикс.

Как передаётся ссылка между базами:

  1. 🔗 РИБ. Объект приходит в другой узел с тем же идентификатором. Ссылка в главном и подчинённом узле одна и та же.
  2. 🔗 Обмен через XML-сериализацию (ЗаписатьXML, планы обмена). В сообщении ссылка — элемент Ref с UUID. При загрузке платформа ищет объект по этому идентификатору; если не нашла, создаёт новый с той же ссылкой.
  3. 🔗 Обмен через правила конвертации (EnterpriseData и др.). Ссылки в разных конфигурациях могут не совпадать. Объекты сопоставляются по UUID, а при неудаче — по полям поиска (ИНН, код, наименование). Соответствия идентификаторов разных баз типовые конфигурации хранят в отдельном регистре сведений подсистемы обмена.

Откуда берутся битые ссылки

Если в базу пришёл документ, а контрагент, на которого он ссылается, ещё не выгружен, реквизит получит ссылку на несуществующий объект. В форме вместо названия появится строка вида:

<Объект не найден> (123:80c9000c29c3b2f411e9e5f6a1b2c3d4)

Число до двоеточия — номер ссылочного типа (тот же, что в имени таблицы _Reference123). После двоеточия — идентификатор в порядке хранения СУБД. По этим двум значениям можно найти, на какой справочник ссылка и какой объект потерялся.

Битые ссылки появляются и без обменов:

  • ⚡ объект удалили непосредственно, минуя пометку на удаление и проверку ссылок;
  • ⚡ загрузили часть данных из другой базы через универсальную выгрузку;
  • ⚡ запись в таблицу изменили SQL-скриптом.

Ошибки при работе со ссылками и как их исправить

Диагностика: выберите симптом

Массовая проверка ссылочной целостности

В конфигураторе откройте Администрирование → Тестирование и исправление, отметьте «Проверка логической целостности» и «Проверка ссылочной целостности». Для найденных битых ссылок есть три варианта: создавать объекты, очищать ссылки или не изменять.

  • «Создавать объекты» — платформа создаст пустые элементы-заглушки с потерянными идентификаторами. Связи сохранятся, а данные заглушек потом можно дозаполнить или подтянуть повторным обменом.
  • «Очищать ссылки» — реквизиты станут пустыми. Восстановить, на что ссылался документ, будет уже нельзя.

Тестирование с исправлением требует монопольного доступа: попросите пользователей выйти и запускайте во внерабочее время. Сделайте резервную копию базы перед запуском — «очистку ссылок» не отменить.

Начинайте с режима «не изменять»: он только покажет, сколько битых ссылок и где. Решение о «создании» или «очистке» принимайте после просмотра списка.

Частые вопросы

Можно ли изменить ссылку у существующего объекта?
Нет. Идентификатор записанного объекта менять нельзя. Нужна другая ссылка — создайте новый объект с заданной через УстановитьСсылкуНового() ссылкой и перенесите связи обработкой поиска и замены ссылок.
Совпадает ли ссылка в копии базы и в файле .dt?
Да. Копия базы, выгрузка .dt и перенос между СУБД сохраняют идентификаторы. Поэтому внешние системы могут хранить UUID и не бояться переноса базы.
Сколько весит ссылка в базе?
16 байт для реквизита одного ссылочного типа. Для составного типа добавляются поле признака и 4-байтовый номер типа.
Почему у перечисления тоже есть ссылка?
Значения перечисления хранятся в отдельной таблице, и реквизит хранит ссылку на её строку. Сравнивать их удобно через Перечисления.Имя.Значение или ЗНАЧЕНИЕ() в запросе.
Чем ссылка отличается от навигационной ссылки?
Ссылка — значение в данных, тип плюс UUID. Навигационная ссылка — текстовый адрес e1cib/... для открытия объекта в интерфейсе; её можно отправить коллеге, и у него откроется та же карточка.