Смена и восстановление уникального идентификатора объекта в 1С 8.3

· 9 мин

Содержание

Две базы вели параллельно, потом решили свести в одну — и один и тот же контрагент приехал с разными идентификаторами. Документы из второй базы ссылаются «в пустоту», обороты не сходятся. Классический случай, когда возникает вопрос: можно ли подменить GUID объекта, чтобы ссылка снова указывала на нужный элемент.

Короткий ответ такой. Задать конкретный уникальный идентификатор можно только новому, ещё не записанному объекту — методом УстановитьСсылкуНового(). У существующего объекта сменить GUID штатными средствами нельзя: идентификатор является ключом, на который завязаны все ссылки. Ниже разберём, когда это вообще нужно, как сделать правильно и почему прямая правка в SQL почти всегда заканчивается разрушением базы.

Статья про платформу 1С:Предприятие 8.3, интерфейс «Такси». Операции с идентификаторами — это разработка, поэтому всё выполняем на тестовой копии, а не на рабочей базе.

Что такое GUID объекта и из чего он состоит

GUID (УникальныйИдентификатор) — это 16-байтовый идентификатор ссылочного объекта: элемента справочника, документа, счёта плана счетов. Он назначается платформой один раз при записи и больше не меняется. Внешне выглядит так: a1b2c3d4-0000-0000-0000-9f8e7d6c5b4a.

Именно по этому значению одна таблица находит объект в другой. Когда в документе указан контрагент, физически в базе хранится не наименование, а GUID ссылки на элемент справочника «Контрагенты». То же самое с регистрами, движениями, реквизитами типа «Ссылка».

Получить идентификатор существующего объекта просто:

ИД = Ссылка.УникальныйИдентификатор();
Сообщить(Строка(ИД)); // a1b2c3d4-0000-0000-0000-9f8e7d6c5b4a

И наоборот — собрать ссылку из известного GUID, не обращаясь к базе:

ИД = Новый УникальныйИдентификатор("a1b2c3d4-0000-0000-0000-9f8e7d6c5b4a");
Ссылка = Справочники.Контрагенты.ПолучитьСсылку(ИД);

ПолучитьСсылку() возвращает ссылку даже если объекта с таким GUID в базе нет. Проверяйте результат через Ссылка.Пустая() или чтение объекта — «висячая» ссылка выглядит как ссылка на удалённый элемент.

Когда реально нужно задавать идентификатор вручную

Задача «сменить GUID» почти всегда означает не «переписать его у объекта», а «создать объект с заранее известным идентификатором». Типичные ситуации:

  • 🔗 Свод двух баз. Один и тот же контрагент/номенклатура в базах получил разные GUID. При объединении нужно, чтобы в целевой базе объект имел тот же идентификатор, что в источнике, — тогда ссылки сойдутся.
  • 🔁 Обмен данными и РИБ. В распределённой информационной базе и в обменах узлы обязаны ссылаться на один и тот же объект одним GUID. Если синхронизацию настраивали вручную, идентификаторы могут разойтись.
  • 📦 Перенос данных . После выгрузки-загрузки через самописную обработку часть ссылок потеряла адресата: объекты перезаписались с новыми идентификаторами.
  • 🧩 Восстановление после сбоя. В резервной копии объект есть, в рабочей базе его случайно удалили и пересоздали — ссылки из старых документов указывают на прежний GUID.

Во всех этих случаях менять идентификатор у уже записанного объекта не нужно и нельзя. Правильный приём — пересоздать объект с нужным GUID либо изначально загружать данные механизмом, который идентификаторы сохраняет.

Программный способ: метод УстановитьСсылкуНового

Это единственный штатный способ задать конкретный GUID. Работает он только для нового объекта — до первой записи.

НоваяСсылка = Справочники.Контрагенты.ПолучитьСсылку(
    Новый УникальныйИдентификатор("a1b2c3d4-0000-0000-0000-9f8e7d6c5b4a"));

Элемент = Справочники.Контрагенты.СоздатьЭлемент();
Элемент.УстановитьСсылкуНового(НоваяСсылка);
Элемент.Наименование = "ООО Ромашка";
Элемент.ИНН = "7701234567";
Элемент.Записать();

После Записать() объект получает именно тот идентификатор, который вы передали. Для документов приём тот же, только вместо СоздатьЭлемент() — СоздатьДокумент().

Что важно помнить:

  • Метод применим до записи. У объекта, который уже есть в базе, вызвать его нельзя — ссылка нового задаётся один раз.
  • Если объект с таким GUID в базе уже существует, запись перезапишет его. Контролируйте уникальность перед вставкой.
  • Код не трогает конфигурацию, поэтому выполнять его удобно из внешней обработки или консоли кода в режиме «1С:Предприятие». Это и есть «программный метод через консоль», о котором часто пишут: не отдельный инструмент, а исполнение скрипта УстановитьСсылкуНового() без изменения структуры.

Если на старый объект уже ссылались документы, простое создание нового объекта с тем же GUID сработает только когда старого объекта в базе нет. Иначе получится два объекта или перезапись — сначала разберитесь, какой из них «правильный».

Для пакетной вставки (например, при интеграции с внешней системой, которая присылает свои идентификаторы) полезно сразу проверять, нет ли объекта с таким GUID:

Ссылка = Справочники.Номенклатура.ПолучитьСсылку(ВнешнийGUID);
Если Ссылка.Пустая() ИЛИ Ссылка.ПолучитьОбъект() = Неопределено Тогда
    Элемент = Справочники.Номенклатура.СоздатьЭлемент();
    Элемент.УстановитьСсылкуНового(Ссылка);
    Элемент.Наименование = Данные.Наименование;
    Элемент.Записать();
КонецЕсли;

Так вы не плодите дубли: объект с нужным идентификатором создаётся только если его ещё нет.

Восстановление объекта с прежним идентификатором

Отдельный частый сценарий — объект случайно удалили, пересоздали заново, и теперь старые документы ссылаются на «потерянный» GUID. Задача: вернуть объект так, чтобы прежние ссылки снова его видели.

Порядок действий:

  1. Восстановите резервную копию в отдельную базу (не поверх рабочей).
  2. Найдите в копии нужный объект и считайте его идентификатор: Строка(Ссылка.УникальныйИдентификатор()).
  3. В рабочей базе проверьте, нет ли уже объекта с таким GUID. Если «новый» дубль успели создать с другим идентификатором — его придётся свести отдельно.
  4. Создайте объект с прежним идентификатором через УстановитьСсылкуНового(), перенеся реквизиты из копии.

После записи документы, ссылавшиеся на старый GUID, снова найдут объект. Если же «новый» объект уже активно использовали, разумнее не восстанавливать старый, а свести два элемента типовой обработкой поиска дублей — иначе получите две сущности с разной историей.

Идентификатор удалённого объекта можно подсмотреть и в движениях регистров резервной копии, если сам объект из справочника уже вычищен, — ссылка в регистре хранит тот же GUID.

Табличный способ: прямая правка идентификатора в СУБД

Под «табличным методом» обычно понимают изменение GUID напрямую в SQL — в поле _IDRRef таблицы ссылочного объекта. Сразу предупрежу: это не поддерживаемый фирмой «1С» способ, и в 99% случаев он ломает базу. Объясню, почему.

Идентификатор объекта хранится не в одном месте. Он лежит в поле _IDRRef самой таблицы объекта и продублирован во всех полях-ссылках, которые на него указывают: реквизиты документов (_Fld..._RRef), измерения и ресурсы регистров, табличные части. Поменяв GUID только в таблице объекта, вы оставляете сотни ссылок, указывающих на старое значение, — объект «теряется».

Есть и чисто технический подвох: в MS SQL Server платформа хранит GUID в поле binary(16) в своём порядке байт, который не совпадает с привычной строковой записью. Один в один подставить строку из конфигуратора не получится — нужна перестановка байтов, и ошибка здесь гарантированно даёт мусор.

Наконец, при любом реструктурировании (обновление конфигурации , тестирование и исправление) платформа сверяет внутренние структуры. База с «ручной» правкой идентификаторов на этом этапе может перестать открываться.

Вывод простой: прямое редактирование _IDRRef в SQL — не инструкция, а антипаттерн. Если звучит соблазн «просто поправим одно поле», вернитесь к программному способу или к штатным механизмам переноса.

Технические ограничения: почему ссылки «отваливаются»

Соберём ограничения в одну картину, чтобы было видно, где именно рвётся связь.

Что меняемЧто происходит со ссылкамиБезопасно?
Создаём новый объект с заданным GUID (УстановитьСсылкуНового)Старые ссылки на этот GUID начинают указывать на новый объектДа, если старого объекта с этим GUID нет
Правим _IDRRef только у объекта в SQLВсе ссылающиеся таблицы продолжают указывать на старое значение — объект «пропадает»Нет
Правим GUID во всех таблицах вручнуюРиск пропустить таблицу, перепутать порядок байт, нарушить индексыНет
Пересоздаём объект и переносим ссылки штатноСсылки переставляются контролируемоДа

Главное ограничение — у идентификатора нет «одной записи». Он размазан по базе как ключ связи. Поэтому задача «сменить GUID существующему объекту» в терминах платформы всегда превращается в задачу «перенести все ссылки на другой объект», а это уже другая операция.

Безопасные альтернативы и лучшие практики

В большинстве реальных случаев менять идентификатор вообще не нужно — есть штатные механизмы, которые либо сохраняют GUID, либо корректно переставляют ссылки.

Выгрузка-загрузка данных XML. Стандартная обработка переноса между идентичными конфигурациями сохраняет идентификаторы объектов. Если вы наполняете пустую базу копией данных — GUID переедут как есть, и подменять ничего не придётся.

Планы обмена и синхронизация. Для постоянно работающих баз правильный ответ — не ручная правка, а настроенный обмен. В РИБ и в типовой синхронизации платформа сама держит идентификаторы согласованными между узлами.

Поиск и удаление дублей. Когда объект задвоился, не трогайте GUID — воспользуйтесь типовой обработкой Поиск и удаление дублей (раздел Администрирование → Обслуживание в типовых конфигурациях на БСП). Она не меняет идентификатор, а переставляет все ссылки с дубля на оставленный элемент, после чего лишний помечает на удаление. Для свода дублей это и есть штатное решение.

Конвертация данных . Для переноса между разными конфигурациями используйте «Конвертацию данных»: правила сопоставления позволяют связывать объекты и при необходимости выравнивать идентификаторы на загрузке.

Фиксируйте соответствие. Если идентификаторы всё же задаёте вручную под интеграцию, ведите таблицу соответствия «внешний ключ → GUID в 1С» на стороне обмена. Тогда при повторной загрузке система находит ранее созданный объект по этой таблице и не создаёт его заново — это надёжнее, чем каждый раз вычислять GUID из данных источника.

Выбрать подход помогает простое дерево:

Что именно нужно сделать с идентификатором?

Типичные ошибки при работе с идентификаторами

  • Правят GUID у записанного объекта кодом. Метода «сменить идентификатор существующего» нет. УстановитьСсылкуНового() вызывают только у нового объекта — попытка применить к записанному ничего не даст.
  • Подставляют строку GUID в SQL как есть. Без перестановки байт в binary(16) получается неверное значение. Это одна из причин «потерянных» объектов после ручной правки.
  • Меняют идентификатор в таблице объекта, забыв про ссылки. Объект есть, а в документах он «пустой» — ссылки остались на старом GUID.
  • Создают дубль вместо замены. Новый объект с тем же GUID при живом старом даёт конфликт или перезапись. Сначала убедитесь, что старого объекта в базе нет.
  • Экспериментируют на рабочей базе. Любые операции с идентификаторами проверяйте на копии. Перед изменениями обязательно снимите резервную копию.
Перед вмешательством в идентификаторы
Выполнено: 0 / 5

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

Можно ли поменять GUID уже записанного объекта штатно?
Нет. Идентификатор задаётся один раз при записи и меняться не может. Задать его можно только новому объекту методом УстановитьСсылкуНового() до первой записи.
Чем «программный метод через консоль» отличается от обработки?
Ничем принципиально. В обоих случаях выполняется код с УстановитьСсылкуНового(). Консоль кода или внешняя обработка — просто способ запустить этот скрипт в режиме «1С:Предприятие», не меняя конфигурацию.
Почему нельзя просто поправить GUID в SQL?
Идентификатор продублирован во всех ссылающихся таблицах, а в MS SQL он хранится в своём порядке байт. Правка только одного поля разрывает связи, а неверный порядок байт даёт мусор. Способ не поддерживается и ломает базу при реструктуризации.
Как свести дубли без смены идентификатора?
Запустите типовую обработку «Поиск и удаление дублей». Она переставит все ссылки с дубля на выбранный элемент и пометит лишний на удаление — идентификаторы при этом не трогаются.
Сохраняются ли GUID при выгрузке и загрузке данных XML?
Да. Стандартная выгрузка-загрузка между идентичными конфигурациями переносит объекты вместе с их идентификаторами, поэтому для наполнения пустой базы менять ничего не нужно.