При работе с механизмом Внешних источников данных (ВИД) в платформе «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 отрабатывают некорректно, платформа не может найти запись с исходным идентификатором и считает ссылку «битой», в результате чего очищает реквизит.
Рассмотрим подробнее, как именно происходит конвертация данных на уровне СУБД. Проведем эксперимент: создадим элемент справочника программно и принудительно установим ему ссылку с определенным УникальныйИдентификатор. Посмотрим, как это отразится в таблицах 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. Это необходимо, если вы настраиваете 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), проблема с очисткой ссылок исчезает, так как ключи начинают совпадать на уровне байтов.
Для того чтобы избежать проблем с сохранением ссылок, рекомендуем придерживаться следующих правил при проектировании системы:
uniqueidentifier, в 1С оно должно быть сопоставлено с типом УникальныйИдентификатор.nvarchar(36). В 1С назначьте это строковое поле ключевым. Ссылки на строковые ключи сохраняются всегда корректно, так как платформа не применяет к ним алгоритмы перестановки байт.Важный момент: Помните, что ссылки на внешние источники данных ведут себя иначе, чем ссылки на внутренние справочники. 1С проверяет существование записи во внешнем источнике в момент записи объекта-владельца. Если внешняя база недоступна или запрос к ней вернул пустой результат из-за ошибки в GUID, ссылка будет стерта без предупреждения пользователя.