В платформе 1С:Предприятие 8 каждый объект информационной базы (элемент справочника, документ, запись регистра и т․д․) обладает уникальным идентификатором — GUID (Globally Unique Identifier)․ Внутренне ссылка (Ссылка) на объект и есть представление этого GUID․ Часто разработчикам возникает задача: имея строковое представление GUID (например, полученное из внешней системы, логов или файла обмена), найти соответствующий объект или получить к нему ссылку прямо в тексте запроса к базе данных․
В данной статье подробно разберем способы получения ссылки по GUID в запросе, особенности работы с типами УникальныйИдентификатор и Ссылка, а также типичные ошибки и лучшие практики․
Теоретические основы: GUID, УникальныйИдентификатор и Ссылка
Перед тем как переходить к коду, важно понимать разницу между типами данных:
- GUID (строка) — символьное представление идентификатора в формате
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx․ Приходит извне или хранится в строковых полях․ - УникальныйИдентификатор (UniqueIdentifier) — встроенный тип платформы 1С, предназначенный для хранения и операций с GUID в памяти․ Создается конструктором
Новый УникальныйИдентификатор(<Строка>)․ - Ссылка (Ref) — тип данных, ссылающийся на конкретный объект метаданных (Справочник․Номенклатура, Документ․РеализацияТоваровУслуг и т;д․)․ Ссылка «знает» свой вид метаданных․
Ключевой момент: В запросах 1С нельзя напрямую сравнивать поле типа Ссылка со строкой․ Необходимо привести строку к типу УникальныйИдентификатор или использовать специальные функции языка запросов․
Способы получения ссылки в коде (на встроенном языке)
Хотя тема статьи — запросы, часто GUID преобразуют в ссылку в коде модуля перед передачей параметром в запрос․ Это самый производительный и читаемый способ для точечных операций․
Метод Менеджера ПолучитьСсылку
У каждого менеджера справочника, документа и т․д․ есть метод ПолучитьСсылку(<УникальныйИдентификатор>)․
// Пример: Получение ссылки на элемент справочника Номенклатура
ГуидСтрока = "09e5174f-551f-11e8-a22b-0800272d9f13";
Попытка
// 1․ Преобразуем строку в объект типа УникальныйИдентификатор
ГуидОбъект = Новый УникальныйИдентификатор(ГуидСтрока);
// 2․ Получаем ссылку нужного типа метаданных
СсылкаНоменклатуры = Справочники․Номенклатура․ПолучитьСсылку(ГуидОбъект);
// Проверка существования (ссылка может быть пустой, если объекта нет)
Если СсылкаНоменклатуры = Справочники․Номенклатура․ПустаяСсылка Тогда
Сообщить("Объект с таким GUID не найден в базе․");
Иначе
// Работаем со ссылкой
Объект = СсылкаНоменклатуры․ПолучитьОбъект;
КонецЕсли;
Исключение
Сообщить("Неверный формат строки GUID: " + ОписаниеОшибки);
КонецПопытки;
Важно: Метод ПолучитьСсылку не обращается к базе данных для проверки существования объекта (в большинстве конфигураций на управляемых формах)․ Он лишь формирует структуру ссылки на основе GUID․ Проверка существования требует вызова ПолучитьОбъект или запроса к БД․
Универсальная функция для произвольного типа метаданных
Если тип метаданных неизвестен заранее (хранится в строке), можно использовать Метаданные:
Функция ПолучитьСсылкуПоГуиду(ИмяМетаданных, ГуидСтрока) Экспорт
Попытка
Гуид = Новый УникальныйИдентификатор(ГуидСтрока);
Менеджер = Метаданные[ИмяМетаданных];
Если Менеджер = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
Возврат Менеджер․ПолучитьСсылку(Гуид);
Исключение
Возврат Неопределено;
КонецПопытки;
КонецФункции
Работа с GUID в языке запросов (SQL-подобный синтаксис 1С)
В запросах к базе данных (объект Запрос) есть свои правила работы с GUID․
Литерал УникальныйИдентификатор в тексте запроса
Язык запросов 1С поддерживает литерал типа УНИКАЛЬНЫЙИДЕНТИФИКАТОР․ Синтаксис:
ВЫБРАТЬ
Номенклатура․Ссылка,
Номенклатура․Наименование
ИЗ
Справочник․Номенклатура КАК Номенклатура
ГДЕ
Номенклатура․Ссылка = ЗНАЧЕНИЕ(УНИКАЛЬНЫЙИДЕНТИФИКАТОР("09e5174f-551f-11e8-a22b-0800272d9f13"))
- ЗНАЧЕНИЕ(․․․) — обязательная конструкция для задания константы в запросе․
- УНИКАЛЬНЫЙИДЕНТИФИКАТОР(«строка») — функция приведения строки к типу УникальныйИдентификатор․
- Сравнение
Ссылка = УникальныйИдентификаторработает корректно, так как платформа неявно приводит типы․
Передача параметра типа УникальныйИдентификатор
Лучшая практика — использовать параметризованные запросы․ Это безопаснее (защита от инъекций) и быстрее (переиспользование плана запроса)․
Запрос = Новый Запрос;
Запрос․Текст =
"ВЫБРАТЬ
| Номенклатура․Ссылка,
| Номенклатура․Наименование
|ИЗ
| Справочник;Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура․Ссылка = &ГуидПараметр";
ГуидОбъект = Новый УникальныйИдентификатор("09e5174f-551f-11e8-a22b-0800272d9f13");
Запрос․УстановитьПараметр("ГуидПараметр", ГуидОбъект);
Результат = Запрос․Выполнить;
Выборка = Результат․Выбрать;
Пока Выборка․Следующий Цикл
// Выборка․Ссылка — это уже полноценная ссылка на объект
КонецЦикла;
Функция ССЫЛКА в запросе (для динамического определения типа)
Если нужно построить ссылку в запросе, зная только строку GUID и имя таблицы (вида метаданных), можно использовать функцию ССЫЛКА(<ВидМетаданных>, <УникальныйИдентификатор>)․
// Пример: Поиск в объединенном наборе данных (редкий кейс)
ВЫБРАТЬ
ССЫЛКА(Справочник․Номенклатура, ЗНАЧЕНИЕ(УНИКАЛЬНЫЙИДЕНТИФИКАТОР("09e5174f-551f-11e8-a22b-0800272d9f13"))) КАК НайденнаяСсылка
Однако чаще всего используется простое сравнение поля Ссылка с параметром, как в п․ 3․2․
Типичные ошибки и подводные камни
Сравнение со строкой вместо УникальныйИдентификатор
Ошибка:
// НЕВЕРНО: Сравнение ссылки со строкой
ГДЕ Номенклатура․Ссылка = "09e5174f-551f-11e8-a22b-0800272d9f13"
Платформа выдаст ошибку несовместимости типов при выполнении запроса․ Всегда оборачивайте строку в ЗНАЧЕНИЕ(УНИКАЛЬНЫЙИДЕНТИФИКАТОР(․․․)) или передавайте параметр типа УникальныйИдентификатор․
Пустые ссылки и NULL
В запросах 1С существует три состояния «пустоты» для ссылочных полей:
- NULL — отсутствие значения в поле БД (например, внешний ключ не заполнен)․ Проверяется:
Поле ЕСТЬ NULL․ - Пустая ссылка — значение
ЗНАЧЕНИЕ(Справочник․Номенклатура․ПустаяСсылка)․ Это валидная ссылка, указывающая в никуда․ Проверяется:Поле = ЗНАЧЕНИЕ(Справочник․Номенклатура․ПустаяСсылка)․ - Неопределено — значение не задано в языке 1С (переменная не инициализирована)․ В запросах как таковом не встречается, но может быть результатом
ПолучитьОбъектдля битой ссылки․
При поиске по GUID, если GUID соответствует пустой ссылке (все нули), запрос вернет записи с пустой ссылкой․ Обычно это исключают условием:
ГДЕ Номенклатура․Ссылка = &Гуид
И Номенклатура․Ссылка <> ЗНАЧЕНИЕ(Справочник․Номенклатура․ПустаяСсылка)
«Битые» ссылки
Битая ссылка — это ссылка (GUID), на которую в базе не существует объекта (удален, повреждена БД)․
- Метод
ПолучитьСсылкув коде НЕ проверяет существование объекта․ Он вернет ссылку даже для несуществующего GUID․ - В запросе условие
Ссылка = &Гуидпросто не вернет строк, если объекта нет (так как нет записи в таблице)․ - Проблема возникает, если битая ссылка уже записана в реквизит другого объекта․ Тогда
Реквизит․ПолучитьОбъектвернетНеопределено․
Для поиска битых ссылок в запросе часто используют ЛЕВОЕ СОЕДИНЕНИЕ с целевой таблицей и проверку ЦелеваяТаблица․Ссылка ЕСТЬ NULL․
Продвинутые сценарии
Пакетное получение ссылок (массив GUID)
Если нужно найти объекты по списку GUID (например, 1000 штук), неэффективно выполнять 1000 запросов или вызовов ПолучитьСсылку․
Вариант А: Временная таблица (наиболее производительно для больших объемов)․
// 1․ Создаем временную таблицу с полем Гуид (УникальныйИдентификатор)
МенеджерВТ = Новый МенеджерВременныхТаблиц;
ТаблицаГуидов = МенеджерВТ․ПолучитьВременнуюТаблицу("ГуидыДляПоиска");
ТаблицаГуидов․Колонки․Добавить("Гуид", Новый ОписаниеТипов("УникальныйИдентификатор"));
// 2․ Заполняем её массивом ГУИДов
НаборЗаписей = ТаблицаГуидов․СоздатьНаборЗаписей;
Для Каждого СтрГуид Из МассивСтрокГуидов Цикл
Запись = НаборЗаписей․Добавить;
Запись․Гуид = Новый УникальныйИдентификатор(СтрГуид);
КонецЦикла;
НаборЗаписей․Записать;
// 3․ Делаем один запрос с JOIN
Запрос․Текст =
"ВЫБРАТЬ
| Номенклатура․Ссылка
|ИЗ
| Справочник․Номенклатура КАК Номенклатура
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Гуиды КАК ГУИДЫ
| ПО Номенклатура․Ссылка = ГУИДЫ․Гуид";
Запрос․УстановитьПараметр("ВТ_Гуиды", ТаблицаГуидов);
Вариант Б: Оператор В (IN) для небольших списков (до нескольких сотен)․
МассивГуидовОбъектов = Новый Массив;
Для Каждого СтрГуид Из МассивСтрокГуидов Цикл
МассивГуидовОбъектов․Добавить(Новый УникальныйИдентификатор(СтрГуид));
КонецЦикла;
Запрос․Текст = "ВЫБРАТЬ Ссылка ИЗ Справочник․Номенклатура ГДЕ Ссылка В(&МассивГуидов)";
Запрос․УстановитьПараметр("МассивГуидов", МассивГуидовОбъектов);
Извлечение GUID из ссылки в запросе
Обратная задача: получить строковое представление GUID из поля Ссылка․
ВЫБРАТЬ
Номенклатура․Ссылка,
ВЫРАЗИТЬ(Номенклатура․Ссылка КАК СТРОКА(36)) КАК ГуидСтрока
ИЗ
Справочник․Номенклатура КАК Номенклатура
Функция ВЫРАЗИТЬ(․․․ КАК СТРОКА(36)) преобразует УникальныйИдентификатор (внутреннее представление ссылки) в читаемую строку формата ․
Резюме: чек-лист лучших практик
- Всегда используйте параметризованные запросы․ Передавайте
Новый УникальныйИдентификатор(Строка)вУстановитьПараметр․ - В тексте запроса используйте конструкцию
ЗНАЧЕНИЕ(УНИКАЛЬНЫЙИДЕНТИФИКАТОР("․․․"))для констант․ - Не сравнивайте Ссылку со строкой напрямую — ошибка типов․
- Помните про ПустуюСсылку․ GUID из нулей (000․․․0) — это валидная пустая ссылка, она существует в любой таблице как значение по умолчанию․
- Для пакетной обработки используйте временные таблицы или оператор
Вс массивом УникальныйИдентификатор․ - Проверку существования объекта делайте через запрос (проверка на пустой результат) или
Ссылка;ПолучитьОбъект <> Неопределенов коде․
Работа с GUID в 1С запросах требует понимания системы типов платформы․ Главное правило: в запросах оперируйте типом УникальныйИдентификатор, а не строкой․ Использование параметров запроса с объектами УникальныйИдентификатор, это стандарт де-факто, обеспечивающий типобезопасность, производительность и защиту от ошибок форматирования строки․ При необходимости массового поиска применяйте временные таблицы для минимизации нагрузки на СУБД․