В практике разработки на платформе 1С:Предприятие часто встречается ситуация, когда внешние данные или записи в регистрах содержат уникальный идентификатор (GUID) в виде строки. При этом возникает необходимость соединить эти данные со справочником или другим объектом для получения дополнительных реквизитов. Напрямую в запросе сравнить Тип.Строка и Тип.СправочникСсылка невозможно. Разберем подробно, как решить эту задачу в зависимости от вашей версии платформы и требований к производительности. Для устранения ошибок несовместимости типов при таких операциях полезно использовать методику сравнения строки с представлением ссылки в запросе.
Проанализируем ситуацию: в платформе 1С до версии 8.3.22 отсутствовали встроенные функции запроса для преобразования типов между строкой и уникальным идентификатором. Ссылка в 1С — это сложный объект, который в базе данных хранится в бинарном виде, а строковое представление (GUID) — это лишь один из способов его отображения. Поскольку типы данных не совпадают, стандартный оператор СОЕДИНЕНИЕ или условие ГДЕ выдадут ошибку или не вернут результат.
Если вы проектируете систему или имеете возможность редактировать структуру регистра, самым правильным и производительным решением будет хранение ссылки непосредственно в базе данных. Посмотрим, почему это важно:
Рассмотрим алгоритм действий:
ОбъектСсылка с типом нужного справочника.ID.
// Пример заполнения ссылки по строковому ГУИДу
Выборка = РегистрыСведений.НашРегистр.Выбрать();
Пока Выборка.Следующий() Цикл
МенеджерЗаписи = РегистрыСведений.НашРегистр.СоздатьМенеджерЗаписи();
ЗаполнитьЗначенияСвойств(МенеджерЗаписи, Выборка);
// Преобразуем строку в ссылку
Попытка
GUID = Новый УникальныйИдентификатор(Выборка.ID);
МенеджерЗаписи.ОбъектСсылка = Справочники.НужныйСправочник.ПолучитьСсылку(GUID);
МенеджерЗаписи.Записать();
Исключение
// Обработка некорректных строк GUID
КонецПопытки;
КонецЦикла;
Не забудьте также добавить логику заполнения поля ОбъектСсылка в модуле набора записей регистра при записи новых данных.
Если изменить структуру регистра нельзя, а версия платформы (например, 8.3.19) не поддерживает функции преобразования в запросе, используем методику "подготовки данных в коде". Выясним, как это сделать по шагам:
ID из нашего регистра в массив.УникальныйИдентификатор и сформируем массив ссылок.Проанализируем пример кода:
// 1. Получаем список уникальных строк из регистра
ЗапросИД = Новый Запрос("ВЫБРАТЬ РАЗЛИЧНЫЕ ID ИЗ РегистрСведений.Данные ГДЕ ID <> """"");
ТаблицаИД = ЗапросИД.Выполнить().Выгрузить();
// 2. Создаем таблицу соответствия "Строка - Ссылка"
ТаблицаСоответствия = Новый ТаблицаЗначений;
ТаблицаСоответствия.Колонки.Добавить("СтрокаИД", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(36)));
ТаблицаСоответствия.Колонки.Добавить("СсылкаНаОбъект", Новый ОписаниеТипов("СправочникСсылка.НужныйСправочник"));
Для Каждого Стр Из ТаблицаИД Цикл
Попытка
НовыйИД = Новый УникальныйИдентификатор(Стр.ID);
НоваяСтрока = ТаблицаСоответствия.Добавить();
НоваяСтрока.СтрокаИД = Стр.ID;
НоваяСтрока.СсылкаНаОбъект = Справочники.НужныйСправочник.ПолучитьСсылку(НовыйИД);
Исключение
Продолжить;
КонецПопытки;
КонецЦикла;
// 3. Загружаем таблицу в запрос
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст =
"ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Соответствие ИЗ &ТаблицаСоответствия КАК ТаблицаСоответствия;
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Регистр.Поле1,
| ВТ.СсылкаНаОбъект
|ИЗ
| РегистрСведений.Данные КАК Регистр
|ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Соответствие КАК ВТ
| ПО Регистр.ID = ВТ.СтрокаИД";
Запрос.УстановитьПараметр("ТаблицаСоответствия", ТаблицаСоответствия);
Результат = Запрос.Выполнить();
Начиная с версии платформы 8.3.22, разработчикам стал доступен мощный функционал для работы с идентификаторами прямо внутри текста запроса. Рассмотрим подробнее новые функции:
УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Ссылка) — преобразует ссылку в тип УникальныйИдентификатор.ИЗСТРОКИ(Строка, "УникальныйИдентификатор") — позволяет на лету превратить строковое поле в идентификатор для сравнения.Посмотрим на пример запроса для новых версий:
ВЫБРАТЬ
Регистр.ID,
Спр.Ссылка
ИЗ
РегистрСведений.Данные КАК Регистр
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.НужныйСправочник КАК Спр
ПО ИЗСТРОКИ(Регистр.ID, "УникальныйИдентификатор") = УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Спр.Ссылка)
Важное примечание: При использовании этого метода в условии ПО или ГДЕ, СУБД не сможет использовать индексы. Это приведет к полному сканированию таблицы (Full Scan), что на больших объемах данных (сотни тысяч записей) будет работать очень медленно.
При работе со строковыми представлениями идентификаторов важно учитывать следующие моменты:
Новый УникальныйИдентификатор() регистр не важен, при обычном сравнении строк в запросе (Строка1 = Строка2) СУБД может учитывать регистр в зависимости от настроек (Collation).550e8400-e29b-41d4-a716-446655440000). Если в строке отсутствуют дефисы или присутствуют лишние пробелы, функции преобразования выдадут ошибку.binary к string в SQL не совпадет со строкой GUID в 1С.Мы рассмотрели три способа решения проблемы. Если вы работаете на старой платформе (до 8.3.22), используйте Решение 2 с временными таблицами. Если вы заботитесь о максимальной скорости работы системы, единственным верным путем будет Решение 1 с добавлением индексированного поля ссылки. Для быстрых отчетов на небольших объемах данных в современных версиях платформы идеально подойдет Решение 3 с использованием функции ИЗСТРОКИ.