Смена и восстановление уникального идентификатора объекта в 1С 8.3
Содержание
Две базы вели параллельно, потом решили свести в одну — и один и тот же контрагент приехал с разными идентификаторами. Документы из второй базы ссылаются «в пустоту», обороты не сходятся. Классический случай, когда возникает вопрос: можно ли подменить 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. Задача: вернуть объект так, чтобы прежние ссылки снова его видели.
Порядок действий:
- Восстановите резервную копию в отдельную базу (не поверх рабочей).
- Найдите в копии нужный объект и считайте его идентификатор:
Строка(Ссылка.УникальныйИдентификатор()). - В рабочей базе проверьте, нет ли уже объекта с таким GUID. Если «новый» дубль успели создать с другим идентификатором — его придётся свести отдельно.
- Создайте объект с прежним идентификатором через
УстановитьСсылкуНового(), перенеся реквизиты из копии.
После записи документы, ссылавшиеся на старый 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 при живом старом даёт конфликт или перезапись. Сначала убедитесь, что старого объекта в базе нет.
- Экспериментируют на рабочей базе. Любые операции с идентификаторами проверяйте на копии. Перед изменениями обязательно снимите резервную копию.
Частые вопросы
Можно ли поменять GUID уже записанного объекта штатно?
УстановитьСсылкуНового() до первой записи.Чем «программный метод через консоль» отличается от обработки?
УстановитьСсылкуНового(). Консоль кода или внешняя обработка — просто способ запустить этот скрипт в режиме «1С:Предприятие», не меняя конфигурацию.