Как изменить GUID значения перечисления в 1С:Предприятие 8?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки, переноса доработок между контурами или при настройке обменов данными разработчики иногда сталкиваются с ситуацией, когда одно и то же значение перечисления в разных информационных базах имеет разные уникальные идентификаторы (GUID / UUID). Это приводит к ошибкам сопоставления объектов или дублированию при интеграциях.

Перечисление в платформе 1С имеет двойственную природу: с одной стороны, его состав задается в дереве метаданных конфигурации, а с другой стороны, в базе данных каждое значение выступает полноценным ссылочным типом данных. Во встроенном языке 1С нет штатного метода вроде УстановитьСсылкуНового() для значений перечислений. Разберем доступные способы решения этой задачи, а также проанализируем сопутствующие риски.

Способ 1. Изменение идентификатора через выгрузку конфигурации в файлы

Самый прямой и корректный с точки зрения целостности структуры метаданных способ — это редактирование описания объекта в исходных файлах конфигурации.

Рассмотрим пошаговый регламент выполнения этой операции:

  1. Выгрузим конфигурацию в файлы через меню Конфигурация → Выгрузить конфигурацию в файлы... (или используем выгрузку проекта в 1C:Enterprise Development Tools / командную строку).
  2. Найдем в каталоге выгрузки XML-файл с описанием нашего перечисления (обычно располагается в подкаталоге Enums/ИмяПеречисления.xml).
  3. Найдем узел метаданных, соответствующий нужному значению (тег EnumValue или Value), и отредактируем значение атрибута uuid, указав требуемый GUID.
  4. Сохраним изменения в файле.
  5. Загрузим файлы обратно в конфигурацию через меню Конфигурация → Загрузить конфигурацию из файлов... и обновим конфигурацию базы данных (F7).

Последствия смены GUID для существующих данных

Проанализируем, что произойдет с данными в информационной базе после смены идентификатора. Если в базе уже были документы, справочники или регистры, в которых было выбрано старое значение перечисления, после обновления платформой базы данных эти ссылки станут битыми — на их месте отобразится строка вида <Объект не найден>.

Платформа хранит ссылки на значения перечислений в таблицах СУБД в виде бинарного 16-байтного идентификатора _IDRREF. Так как старый GUID удален из метаданных, СУБД не сможет сопоставить старую бинарную ссылку с обновленным перечислением.

Чтобы избежать появления битых ссылок, выполним один из следующих сценариев:

  1. Предварительная замена: до редактирования XML создаем временное значение перечисления, групповой обработкой переносим на него все ссылки из документов и регистров, затем меняем GUID у основного значения и возвращаем ссылки назад.
  2. Восстановление после обновления: если замена не была сделана заранее, используем стандартную обработку «Поиск и замена дублей» из состава БСП либо программно перебираем ссылки методом НайтиПоСсылкам() и заменяем битые ссылки на обновленное значение.

Способ 2. Штатное пересоздание значения в конфигураторе

Если нет возможности выгружать всю конфигурацию в файлы, разберем альтернативный путь через поэтапное обновление информационной базы:

  1. Создаем в перечислении новое значение с временным именем (например, Значение_Новое).
  2. Применяем изменения к базе данных (F7).
  3. С помощью обработки «Поиск и замена ссылок» переносим все ссылки со старого значения на новое.
  4. Удаляем старое значение перечисления в конфигураторе и снова обновляем базу данных.
  5. Переименовываем новое значение в правильное имя и выполняем финальное обновление базы данных.

Программный анализ структуры хранения перечислений в СУБД

Посмотрим на пример кода на встроенном языке 1С, который позволяет получить соответствие имен значений перечисления и их номеров порядка (_ENUMORDER) в физической таблице базы данных:


Функция СоздатьТаблицуПеречислений(ИмяПеречисления)
    Массив = Новый Массив;
    Массив.Добавить("Перечисление." + ИмяПеречисления);
    
    СтруктураБД = ПолучитьСтруктуруХраненияБазыДанных(Массив, Истина);
    СтрТаблицы = СтруктураБД.Найти("Перечисление." + ИмяПеречисления, "ИмяТаблицы");
    
    Мета = Метаданные.Перечисления[ИмяПеречисления];
    ОбъектПеречисление = Перечисления[ИмяПеречисления];
    
    ТекстЗапроса = "SELECT _IDRREF AS Ссылка, CASE ";
    
    Для Каждого ЗначениеМета Из Мета.ЗначенияПеречисления Цикл
        ИндексЗначения = ОбъектПеречисление.Индекс(ОбъектПеречисление[ЗначениеМета.Имя]);
        ТекстЗапроса = ТекстЗапроса + " WHEN _ENUMORDER = " + ИндексЗначения + " THEN '" + ЗначениеМета.Имя + "'";
    КонецЦикла;
    
    ТекстЗапроса = ТекстЗапроса + " END AS ИмяЗначения FROM " + СтрТаблицы.ИмяТаблицыХранения + ";";
    Возврат ТекстЗапроса;
КонецФункции

Прямая замена через SQL: особенности и ограничения

Иногда разработчики рассматривают вариант прямого обновления ссылок в таблицах СУБД с помощью скриптов, подобных следующему пакетному обновлению:


DECLARE @table TABLE(row_n INT IDENTITY(1,1), table_n NVARCHAR(500), col_n NVARCHAR(500))
DECLARE @iterator INT = 1
DECLARE @query NVARCHAR(1024)

INSERT INTO @table(table_n, col_n) 
SELECT TABLE_NAME, COLUMN_NAME 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE DATA_TYPE = 'binary' AND COLUMN_NAME LIKE '%Ref%' AND CHARACTER_MAXIMUM_LENGTH = 16

WHILE @iterator <= (SELECT MAX(row_n) FROM @table)
BEGIN
    SELECT @query = 'UPDATE ' + table_n + ' SET ' + col_n + ' = 0x8D4300155D007A5E11E3E65DF3EFDBB6 WHERE ' + col_n + ' = 0x8D4300155D007A5E11E3E57BD49E16A2' 
    FROM @table WHERE row_n = @iterator

    EXEC sys.sp_executesql @query
    SET @iterator = @iterator + 1
END

Важно понимать: прямая модификация таблиц базы данных в обход платформы 1С не рекомендуется по следующим причинам:

  1. Кэширование кластера 1С: сервер 1С кэширует идентификаторы и таблицы метаданных. Прямое изменение в СУБД приводит к рассинхронизации серверного кэша и ошибкам чтения данных.
  2. Планы обмена: прямые SQL-запросы не регистрируют изменения в узлах планов обмена, что нарушит корректность последующей синхронизации распределенной информационной базы.
  3. Порядок байтов: представление UUID во встроенном языке 1С и в бинарном формате СУБД (_IDRREF) различается из-за специфического порядка байтов платформы.

Наиболее безопасным и надежным методом остается редактирование файлов выгрузки конфигурации с последующей регламентной обработкой ссылок средствами платформы.

← На главную