При работе с Внешними источниками данных (ВИД) разработчики часто сталкиваются с ситуацией, когда необходимо сопоставить данные из внешней базы данных (например, SQL Server или PostgreSQL) с объектами текущей базы 1С. Типичный сценарий: внешний запрос возвращает идентификатор объекта в формате binary(16), который по сути является _IDRRef (внутренним уникальным идентификатором) объекта 1С. Однако платформа 1С по умолчанию воспринимает такие данные как «Двоичные данные», а не как ссылку на справочник или документ.
В этой статье мы разберем несколько эффективных способов «объяснить» системе, что набор байтов из внешнего источника — это готовая ссылка на Справочник.Номенклатура или любой другой объект.
Один из самых производительных способов заключается в подготовке данных еще до того, как они попадут в 1С. Если мы не можем изменить структуру внешней таблицы, мы можем создать Представление (VIEW) на стороне сервера SQL.
Основная сложность здесь заключается в порядке байтов. 1С хранит GUID в базе данных в инвертированном виде. Чтобы 1С корректно распознала строку как УникальныйИдентификатор, ее нужно правильно сконкатенировать на стороне SQL. Проанализируем пример функции для SQL Server, которая превращает binary(16) в строковое представление, понятное для 1С:
SELECT
-- Преобразуем бинарные данные в строку нужного формата
LOWER(CONVERT(NVARCHAR(36), CAST(BinaryField AS UNIQUEIDENTIFIER))) as GUIDString
FROM ExternalTable
Однако помните: стандартный NEWID() в SQL и 1С-овский _IDRRef имеют разную последовательность групп байтов. При создании VIEW убедитесь, что вы получаете строку именно в том порядке, который ожидает конструктор Новый УникальныйИдентификатор(). После того как во внешнем источнике появится поле типа «Строка» с ГУИДом, мы сможем легко преобразовать его в ссылку в коде 1С.
Существует заблуждение, что создание ссылок из уникальных идентификаторов в цикле — это медленная операция, нагружающая базу данных. Это не так. Рассмотрим, почему этот метод эффективен.
Метод Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаГП)) является «чистой» математической операцией. В этот момент 1С не обращается к SQL-серверу. Она просто создает объект ссылки в оперативной памяти на основе переданного идентификатора. Обращение к базе произойдет только тогда, когда вы попытаетесь получить реквизит этой ссылки (например, Ссылка.Наименование).
Разберем алгоритм быстрой обработки данных:
ТаблицаЗначений.ПолучитьСсылку().Пример кода для обработки тысяч записей:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВнешняяТаблица.Идентификатор КАК ИдСтрока
|ИЗ
| ВнешнийИсточникДанных.ВнешняяБД.Таблица КАК ВнешняяТаблица";
ТЗ = Запрос.Выполнить().Выгрузить();
ТЗ.Колонки.Добавить("НоменклатураСсылка", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
Для Каждого Стр Из ТЗ Цикл
// Предполагаем, что ИдСтрока — это строковый GUID из SQL
Попытка
УИД = Новый УникальныйИдентификатор(Стр.ИдСтрока);
Стр.НоменклатураСсылка = Справочники.Номенклатура.ПолучитьСсылку(УИД);
Исключение
// Обработка некорректных данных
КонецПопытки;
КонецЦикла;
Начиная с версии платформы 8.3.5, 1С поддерживает запросы, в которых одновременно участвуют таблицы из Внешних источников данных и таблицы самой информационной базы. Это позволяет нам делегировать сопоставление типов самой платформе.
Проанализируем ситуацию: если во внешней таблице есть поле, по которому можно однозначно идентифицировать номенклатуру (например, Код, Артикул или тот же ГУИД в виде строки), мы можем написать прямой запрос.
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка
ИЗ
ВнешнийИсточникДанных.МояВнешняяБД.ТаблицаЗапроса КАК ВнешниеДанные
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
ПО ВнешниеДанные.Код = Номенклатура.Код
Важный нюанс: при выполнении таких запросов 1С может сначала выгрузить данные из внешнего источника во временную таблицу в основной базе данных, а затем выполнить соединение. Если внешняя таблица содержит миллионы записей, это может вызвать задержку. Рекомендуется максимально фильтровать данные на стороне внешнего источника (используя параметры запроса) перед соединением.
Если данные получаются не через стандартный механизм ВИД, а через ADODB.Connection, то значение binary(16) возвращается в 1С как COMSafeArray (массив байтов). Для его преобразования в ссылку удобно использовать промежуточную функцию конвертации байтов в шестнадцатеричную строку, которую затем принимает конструктор УникальныйИдентификатор.
Рассмотрим логику: 1С ожидает строку ГУИД в формате "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX". Ваша задача — прочитать массив из 16 байт и собрать из них эту строку. Помните о специфике 1С: группы байтов в _IDRRef часто записаны в обратном порядке относительно стандартного GUID.
Если задача сопоставления стоит остро и выполняется часто, рассмотрим вариант оптимизации архитектуры. Мы можем добавить в справочник Номенклатура дополнительный реквизит ВнешнийИдентификатор (тип Строка, длина 36, Индексировать).
При записи новой номенклатуры в 1С мы записываем в это поле строковое представление ее ГУИДа или идентификатор из внешней системы. Тогда работа с внешним источником сводится к простому и очень быстрому соединению в запросе по индексированному полю, что избавляет нас от любых манипуляций с типами binary.
Выбор метода зависит от ваших ограничений:
JOIN между ВИД и справочником 1С.Важное предостережение: Избегайте "алхимии" с подменой таблиц 1С на уровне СУБД (через создание вьюх с именами таблиц 1С). Это может привести к фатальным ошибкам при реструктуризации базы данных или при выполнении тестирования и исправления (ТиИ).