Смена уникального идентификатора ссылки в 1С 8.3: новый объект, перенос ссылок, откат
Содержание
Заменить GUID у уже записанного объекта в 1С 8.3 штатно нельзя: ссылка неизменна с момента первой записи. Рабочий способ другой — создать копию объекта с нужным уникальным идентификатором через УстановитьСсылкуНового(), перевести на неё все ссылки в базе и удалить старый объект.
Типичная ситуация: после переноса данных из другой базы контрагент «Альфа» оказался с другим GUID, чем в учётной системе холдинга. Обмен по идентификаторам перестал его узнавать и плодит дубли. Сменить идентификатор объекта можно безопасно — кодом, обработкой БСП, через Конфигуратор или XML, а SQL оставить на крайний случай.
Когда смена GUID нужна, а когда хватит другого решения
GUID (тип УникальныйИдентификатор) — это 16 байт, которые платформа хранит в поле ссылки. По нему связаны все документы, регистры, реквизиты и табличные части. Поэтому «поменять GUID» на деле значит «поменять ссылку во всех местах, где она встречается».
Реальные причины, по которым за это берутся:
- 🔗 Синхронизация по идентификаторам. Две базы обмениваются данными по GUID, а один и тот же объект в них заведён с разными ссылками.
- 🧩 Восстановление удалённого объекта. Элемент удалили, а в документах остались ссылки вида
<Объект не найден> (75:a1b2...). Нужно вернуть объект именно с тем GUID, на который они указывают. - 📦 Слияние баз. При переносе справочников из одной базы в другую совпали или, наоборот, разошлись идентификаторы.
- 🔁 Внешняя система. Сайт, CRM или складская программа хранит GUID из 1С, и объект пришлось пересоздать.
Если задача в том, чтобы убрать дубль, GUID трогать не нужно. Достаточно объединить элементы: все ссылки переводятся на «правильный» элемент, лишний удаляется. Если обмен идёт по правилам конвертации с поиском по ИНН или коду, иногда проще поправить сопоставление объектов, чем идентификатор.
Сравнение способов
| Способ | Когда подходит | Риски |
|---|---|---|
Копия с УстановитьСсылкуНового() + замена ссылок | Любая конфигурация, объект существует | Долго на больших базах, нужны права администратора |
| Тестирование и исправление с созданием объектов | Объект удалён, остались битые ссылки | Создаются пустые заглушки, их надо заполнить |
| Выгрузка в XML, правка, загрузка | Перенос объектов между базами с нужным GUID | Загрузка без проверок, легко сломать связи |
| Прямой UPDATE в SQL | Последний вариант, клиент-серверная база | Пропущенная таблица = битые данные, без поддержки |
Как узнать текущий GUID объекта и битой ссылки
Прежде чем что-то менять, нужно знать оба идентификатора: старый и целевой.
Получить GUID существующей ссылки можно одной строкой кода. Например, в консоли кода или во внешней обработке:
УИД = Ссылка.УникальныйИдентификатор();
Сообщить(Строка(УИД)); // 1cbec0e1-8e7d-11df-aa1b-001a6463a6ca
Метод работает и для битой ссылки, на которую уже нет объекта. Это удобно: GUID удалённого элемента достаётся прямо из реквизита документа.
Из текстового представления <Объект не найден> идентификатор тоже извлекается. Строка вида <Объект не найден> (79:aa1b001a6463a6ca11df8e7d1cbec0e1) содержит номер таблицы и 32 hex-символа в порядке хранения. Чтобы собрать GUID, группы переставляют:
| Часть в строке | Символы | Место в GUID |
|---|---|---|
| 1–4 символа | aa1b | 4-я группа |
| 5–16 | 001a6463a6ca | 5-я группа |
| 17–20 | 11df | 3-я группа |
| 21–24 | 8e7d | 2-я группа |
| 25–32 | 1cbec0e1 | 1-я группа |
Итог: 1cbec0e1-8e7d-11df-aa1b-001a6463a6ca. В таком же порядке байты лежат в поле _IDRRef на SQL Server. Число перед двоеточием — внутренний номер таблицы, для сборки GUID оно не нужно.
Не собирайте идентификатор вручную, если можно взять его кодом из реквизита. Одна перепутанная группа — и вы создадите объект, на который ничего не ссылается.
Замена GUID объекта в 1С кодом: копия, перенос ссылок, удаление
Это основной и самый безопасный путь. Он работает в файловой и клиент-серверной базе и не выходит за рамки платформы.
Перед началом сделайте резервную копию базы (выгрузку .dt или бэкап СУБД). Замена ссылок затрагивает сотни таблиц, и откатить её вручную почти невозможно.
Шаг 1. Создайте новый объект с нужным GUID
Код выполняется на сервере: во внешней обработке или в консоли кода с правами администратора.
&НаСервереБезКонтекста
Функция СоздатьКопиюСНовымGUID(СтараяСсылка, СтрокаGUID)
НовыйУИД = Новый УникальныйИдентификатор(СтрокаGUID);
МенеджерОбъекта = ОбщегоНазначения.МенеджерОбъектаПоСсылке(СтараяСсылка);
НоваяСсылка = МенеджерОбъекта.ПолучитьСсылку(НовыйУИД);
Если НоваяСсылка.ПолучитьОбъект() <> Неопределено Тогда
ВызватьИсключение "Объект с таким GUID уже существует";
КонецЕсли;
НовыйОбъект = СтараяСсылка.ПолучитьОбъект().Скопировать();
НовыйОбъект.УстановитьСсылкуНового(НоваяСсылка);
НовыйОбъект.Записать();
Возврат НоваяСсылка;
КонецФункции
ОбщегоНазначения.МенеджерОбъектаПоСсылке() есть в конфигурациях на БСП (БП 3.0, ЗУП 3.1, УТ 11). В самописной базе менеджер берите напрямую: Справочники.Контрагенты.
Несколько тонкостей:
- ⚠️ Контроль уникальности кода. Если в справочнике он включён, копия с прежним кодом не запишется. Очистите код у копии, а после удаления старого элемента верните прежний.
- 📄 Документы. Копию записывайте в режиме
РежимЗаписиДокумента.Запись, без проведения. Иначе на время работы в регистрах окажутся двойные движения. - 🗂️ Подчинённые данные. Скопируются реквизиты и табличные части. Присоединённые файлы, контактная информация в отдельных регистрах и история версий останутся на старой ссылке, пока вы не замените ссылки.
Шаг 2. Переведите все ссылки со старого объекта на новый
В типовых конфигурациях для этого есть готовая функция БСП ОбщегоНазначения.ЗаменитьСсылки(). Она обходит все таблицы, где встречается ссылка, включая регистры и составные типы.
ПарыЗамен = Новый Соответствие;
ПарыЗамен.Вставить(СтараяСсылка, НоваяСсылка);
ПараметрыЗамены = Новый Структура;
ПараметрыЗамены.Вставить("СпособУдаления", "Пометка");
Ошибки = ОбщегоНазначения.ЗаменитьСсылки(ПарыЗамен, ПараметрыЗамены);
Для Каждого Ошибка Из Ошибки Цикл
Сообщить(Ошибка.ТекстОшибки);
КонецЦикла;
Набор параметров зависит от версии БСП, поэтому сверьтесь с комментарием к функции в общем модуле ОбщегоНазначения вашей конфигурации.
Без программирования то же самое делает обработка «Поиск и удаление дублей». В БП 3.0 она открывается из Администрирование → Обслуживание → Корректировка данных. Найдите пару «старый — новый» и выберите новый элемент как оригинал: обработка заменит ссылки и пометит старый на удаление.
В конфигурации без БСП ссылки собирают методом НайтиПоСсылкам(). Он вернёт таблицу со всеми объектами и записями регистров, где встречается старая ссылка. Каждую найденную запись придётся перезаписать отдельно — это долгая ручная работа, проще встроить в базу общий модуль с аналогичной логикой.
Шаг 3. Проверьте и удалите старый объект
- Повторно вызовите
НайтиПоСсылкам()для старой ссылки. Таблица должна быть пустой. - Проведите новый документ, если это документ.
- Удалите старый объект через «Удаление помеченных объектов».
- Сформируйте контрольные отчёты: оборотно-сальдовую ведомость по счёту объекта, остатки по регистрам.
Как вернуть удалённый объект по прежнему GUID
Здесь замена ссылок не нужна: битые ссылки уже указывают на нужный GUID. Достаточно создать объект именно с этим идентификатором, и все документы «оживут».
Через Конфигуратор: тестирование и исправление
В Конфигураторе выберите Администрирование → Тестирование и исправление. Отметьте проверку ссылочной целостности и в настройке для ссылок на несуществующие объекты выберите вариант «Создавать объекты».
Платформа создаст объекты-заглушки с теми GUID, на которые есть ссылки. Наименование у них служебное, реквизиты пустые. Найдите заглушки в справочнике и заполните вручную или кодом.
Тестирование и исправление требует монопольного доступа. Все пользователи должны выйти из базы, их сеансы будут недоступны до окончания проверки. Запускайте вне рабочего времени и после резервной копии.
В режиме Предприятия кодом
Если битых ссылок мало и вы точно знаете GUID, создайте один объект без остановки работы:
УИД = Новый УникальныйИдентификатор("1cbec0e1-8e7d-11df-aa1b-001a6463a6ca");
Ссылка = Справочники.Номенклатура.ПолучитьСсылку(УИД);
Если Ссылка.ПолучитьОбъект() = Неопределено Тогда
Объект = Справочники.Номенклатура.СоздатьЭлемент();
Объект.УстановитьСсылкуНового(Ссылка);
Объект.Наименование = "Восстановленный элемент";
Объект.Записать();
КонецЕсли;
После записи все реквизиты, где стояло <Объект не найден>, покажут новое наименование.
Перенос объекта с заданным GUID через XML
Когда объект нужно перенести в другую базу с конкретным идентификатором, удобна универсальная обработка выгрузки и загрузки данных XML. Её распространяют для 8.3 как внешнюю обработку .
Порядок такой:
- Выгрузите объект из исходной базы в XML-файл.
- Откройте файл в текстовом редакторе и найдите тег
<Ref>нужного объекта. - Подставьте целевой GUID в обычном формате с дефисами. Замените его и во всех местах файла, где этот объект упоминается.
- Загрузите файл в приёмник той же обработкой.
Загрузка идёт в режиме обмена данными: проверки заполнения и обработчики записи не срабатывают. Документы после загрузки проведите отдельно и проверьте остатки.
Не используйте этот путь внутри одной базы для «переименования» GUID: старый объект останется, а ссылки на него не изменятся.
Прямая замена идентификатора через SQL
На SQL Server или PostgreSQL ссылка лежит в поле _IDRRef типа binary(16) (в PostgreSQL — bytea). Ссылки на объект хранятся в полях _Fld…RRef всех таблиц, где он встречается. Для составных типов — ещё и в паре полей с номером типа.
Соответствие имён таблиц объектам конфигурации покажет функция ПолучитьСтруктуруХраненияБазыДанных().
Фрагмент для одной таблицы выглядит так (SQL Server):
-- Только для иллюстрации: меняет ссылку в одной таблице
UPDATE _Reference75
SET _IDRRef = 0xAA1B001A6463A6CA11DF8E7D1CBEC0E1
WHERE _IDRRef = 0x<старый идентификатор>;
Почему этот способ — последний:
- ❌ Нужно обновить все поля во всех таблицах: документы, табличные части, регистры, итоги, историю версий, таблицы регистрации изменений. Пропустили одну — получили битые данные.
- ❌ Платформа не узнает об изменениях: не обновятся итоги и полнотекстовый индекс, не зарегистрируются изменения для обмена.
- ❌ Фирма 1С не поддерживает прямое изменение данных в таблицах базы. Если после правки база начнёт сбоить, разбираться придётся самостоятельно.
- ❌ В файловой базе этот путь закрыт.
Если без SQL не обойтись, делайте его на копии базы. Остановите доступ пользователей, после правки выполните в Конфигураторе тестирование и исправление с пересчётом итогов. Сеансы на время работ будут прерваны, поэтому выбирайте нерабочее окно.
GUID в распределённой базе и обменах
В распределённой информационной базе (РИБ) GUID объекта одинаков во всех узлах. Это упрощает одно и усложняет другое.
Что работает в вашу пользу. Новый объект, созданный с УстановитьСсылкуНового() в главном узле, приходит в подчинённые с тем же идентификатором.
Что нужно учесть:
- 📤 Замена ссылок регистрирует к обмену каждый изменённый документ и набор записей. После замены в популярном справочнике пакет обмена может вырасти в разы.
- 🏢 Выполняйте замену в главном узле, когда все узлы синхронизированы. Затем проведите обмен со всеми узлами по очереди.
- 🚫 Правка через SQL в РИБ не регистрирует изменения. Узлы разойдутся: в одном объект с новым GUID, в другом — со старым.
В обменах по правилам конвертации (базы с разными конфигурациями) смена GUID ломает сопоставление. Приёмник по старому идентификатору объекта не найдёт и создаст новый. В конфигурациях на БСП сопоставление хранится в регистре сведений «Соответствия объектов информационных баз». После смены GUID проверьте запись для этого объекта или выполните повторное сопоставление в настройках синхронизации.
Риски и откат, если что-то пошло не так
Что чаще всего ломается и как это исправить:
Полный откат — только из резервной копии. Поэтому сохраняйте её до начала и не удаляйте, пока не убедитесь, что отчёты и обмены работают.
Частые вопросы
Можно ли поменять GUID у предопределённого элемента?
Сохранит ли новый объект номер и дату документа?
Скопировать() переносит реквизиты и табличные части. Номер и дату проверьте у копии до записи и при необходимости присвойте прежние; при контроле уникальности номера действуйте так же, как с кодом справочника.Можно ли сгенерировать GUID заранее, до создания объекта?
Новый УникальныйИдентификатор() без параметров даёт случайный GUID. Его можно передать во внешнюю систему и потом создать объект с этой ссылкой.