Почему не сохраняется ссылка на внешний источник данных в реквизите справочника

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

При работе с механизмом Внешних источников данных (ВИД) в платформе «1С:Предприятие 8.3» разработчики часто сталкиваются с ситуацией, когда ссылка на объект внешней таблицы, выбранная в реквизите справочника или документа, исчезает сразу после записи объекта. В интерфейсе это выглядит так: пользователь выбирает значение из списка внешней таблицы, поле заполняется, но после нажатия кнопки «Записать» или при повторном открытии формы поле оказывается пустым. Рассмотрим причины этого поведения и разберем способы решения проблемы, связанные с особенностями хранения данных в СУБД MS SQL Server.

Механизм перестановки байт в уникальных идентификаторах

Проанализируем ситуацию: основной причиной «потери» ссылки является специфический алгоритм работы платформы 1С с типом данных uniqueidentifier (GUID) во внешних базах данных. Согласно документации ИТС, при записи уникального идентификатора в поле таблицы внешнего источника данных платформа выполняет перестановку байт (так называемый byte shuffling). Это делается для оптимизации хранения и индексации данных внутри самой 1С, так как внутренний формат 1С (binary(16)) отличается от стандартного представления uniqueidentifier в SQL Server.

Выясним причину на конкретном примере. Предположим, у нас есть идентификатор в 1С:

a0e55759-35f1-400c-8169-e5edbc2486ba

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

ede56981-24bc-ba86-400c-35f1a0e55759

Проблема заключается в том, что при попытке обратного чтения или сопоставления ссылки во время записи основного объекта (например, справочника), 1С выполняет запрос к внешней таблице. Если настройки сопоставления типов в конфигураторе или драйвер ODBC отрабатывают некорректно, платформа не может найти запись с исходным идентификатором и считает ссылку «битой», в результате чего очищает реквизит.

Технический анализ трансформации GUID в SQL

Рассмотрим подробнее, как именно происходит конвертация данных на уровне СУБД. Проведем эксперимент: создадим элемент справочника программно и принудительно установим ему ссылку с определенным УникальныйИдентификатор. Посмотрим, как это отразится в таблицах SQL.


// Пример программной установки ссылки для анализа в SQL
ТестЭлемент = Справочники.Контрагенты.СоздатьЭлемент();
ГУИД = Новый УникальныйИдентификатор("a0e55759-35f1-400c-8169-e5edbc2486ba");
Ссылка = Справочники.Контрагенты.ПолучитьСсылку(ГУИД);

ТестЭлемент.УстановитьСсылкуНового(Ссылка);
ТестЭлемент.Наименование = "Тестовая запись для анализа GUID";
ТестЭлемент.Записать();

Теперь проанализируем, как эти данные хранятся в SQL Server. Если мы выполним запрос к таблице этого справочника и попробуем конвертировать внутреннее бинарное поле ссылки в стандартный uniqueidentifier, мы увидим ту самую перестановку байт.


SELECT 
    [_IDRRef] AS [Внутренний_Бинарный_Вид],
    [_Description] AS [Наименование],
    CONVERT(UNIQUEIDENTIFIER, [_IDRRef]) AS [SQL_GUID_Представление]
FROM [dbo].[_Reference47] 
-- Где _Reference47 - имя таблицы справочника в SQL

В результате мы увидим, что значение 0x8169E5EDBC2486BA400C35F1A0E55759 превращается в SQL-ный GUID, который не совпадает визуально с тем, что мы видели в 1С. Именно это несовпадение при поиске по ключу во внешнем источнике данных приводит к очистке поля.

Восстановление соответствия идентификаторов 1С и SQL

Разберем, как получить «чистое» представление идентификатора 1С непосредственно средствами SQL. Это необходимо, если вы настраиваете View (Представление) в SQL для подключения его как внешнего источника. Чтобы 1С корректно видела свои идентификаторы, можно использовать следующую формулу трансформации в SQL-запросе:


SELECT 
    [_IDRRef],
    CAST([_IDRRef] AS UNIQUEIDENTIFIER) AS GUID_SQL,
    CAST(
        CAST(REVERSE(SUBSTRING([_IDRRef], 9, 8)) AS BINARY(8)) + 
        SUBSTRING([_IDRRef], 1, 8) 
    AS UNIQUEIDENTIFIER) AS GUID_1C
FROM [dbo].[_Reference47]

В данном запросе мы выполняем реверс части бинарной последовательности. Это позволяет получить в колонке GUID_1C именно то строковое представление, которое ожидает платформа 1С. При использовании такого подхода в качестве основы для внешнего источника данных (через SQL View), проблема с очисткой ссылок исчезает, так как ключи начинают совпадать на уровне байтов.

Рекомендации по настройке внешних источников данных

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

  1. Проверка ключевых полей: Убедитесь, что в конфигураторе для таблицы внешнего источника данных правильно определен «Ключ». Если ключевое поле в SQL имеет тип uniqueidentifier, в 1С оно должно быть сопоставлено с типом УникальныйИдентификатор.
  2. Использование строковых представлений: Если автоматическая конвертация GUID работает нестабильно (особенно на старых версиях драйверов ODBC), создайте в SQL Представление (View), где идентификатор будет приведен к строковому типу nvarchar(36). В 1С назначьте это строковое поле ключевым. Ссылки на строковые ключи сохраняются всегда корректно, так как платформа не применяет к ним алгоритмы перестановки байт.
  3. Обновление драйверов ODBC: Используйте актуальные версии драйверов (например, ODBC Driver 17 for SQL Server). Разные версии драйверов могут по-разному транслировать бинарные данные, что влияет на сопоставление ссылок платформой.
  4. Синхронизация типов: Проверьте, что длина и точность типов данных во внешней таблице соответствуют настройкам в метаданных 1С. Любое несоответствие может привести к тому, что 1С не сможет идентифицировать объект при записи.

Важный момент: Помните, что ссылки на внешние источники данных ведут себя иначе, чем ссылки на внутренние справочники. 1С проверяет существование записи во внешнем источнике в момент записи объекта-владельца. Если внешняя база недоступна или запрос к ней вернул пустой результат из-за ошибки в GUID, ссылка будет стерта без предупреждения пользователя.

← На главную