При разработке механизмов интеграции, обменов данными через распределенные информационные базы (РИБ) или веб-сервисы разработчики часто сталкиваются с понятием «битой» (неразрешимой) ссылки. Такая ссылка представляет собой объект типа Ссылка, для которого в информационной базе отсутствует соответствующая запись в таблице объекта (в интерфейсе это отображается как «<Объект не найден>...»).
Рассмотрим, можно ли использовать такую ссылку в качестве условия фильтрации в запросе, почему возникают ошибки и как правильно передавать битую ссылку в параметры запроса.
Разберем внутреннее устройство ссылочного типа данных. На уровне СУБД ссылочные реквизиты хранятся как 16-байтные бинарные идентификаторы (GUID). Когда в запросе выполняется простое прямое сравнение на равенство, например ГДЕ Документ.Реквизит = &Параметр, платформа 1С передает СУБД команду сравнить байты в колонке таблицы. При этом обращение к самой таблице отсутствующего объекта не происходит.
Это означает, что условие на равенство с битой ссылкой полноценно работает, если в параметр передана корректно сформированная ссылка нужного типа с тем же самым уникальным идентификатором.
Выясним причину частой ошибки: попытка передать в параметр строку вида "<Объект не найден>..." или строковое представление GUID приведет к пустому результату запроса, так как типы данных не совпадут. Передавать необходимо именно объект ссылочного типа.
Разберем по шагам, как получить ссылку по известному идентификатору и применить её в запросе:
УникальныйИдентификатор.ПолучитьСсылку() для создания ссылки. Даже если объекта физически нет в базе, метод вернет валидную ссылку с указанным GUID.Посмотрим на пример кода:
// Строковый GUID битой ссылки (например, полученный из внешнего сервиса или пакета обмена)
СтрокаGUID = "a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d";
// 1. Создаем объект уникального идентификатора
Идентификатор = Новый УникальныйИдентификатор(СтрокаGUID);
// 2. Получаем ссылку через менеджер соответствующего метаданного
БитаяСсылка = Документы.ЗаказПоставщику.ПолучитьСсылку(Идентификатор);
// 3. Формируем и выполняем запрос
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЗаказКлиента.Ссылка КАК Ссылка,
| ЗаказКлиента.Номер КАК Номер,
| ЗаказКлиента.Дата КАК Дата
|ИЗ
| Документ.ЗаказКлиента КАК ЗаказКлиента
|ГДЕ
| ЗаказКлиента.ЗаказПоставщику = &БитаяСсылка";
Запрос.УстановитьПараметр("БитаяСсылка", БитаяСсылка);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Обработка найденных документов
КонецЦикла;
Проанализируем ситуации, при которых запрос с битой ссылкой может вернуть непредвиденный результат или работать некорректно:
ВЫБРАТЬ или ГДЕ обратиться к реквизиту отсутствующего объекта (например, ЗаказПоставщику.Номер), платформа автоматически сформирует ЛЕВОЕ СОЕДИНЕНИЕ с таблицей отсутствующего объекта. Так как записи нет, результатом выражения всегда будет NULL.ВНУТРЕННЕЕ СОЕДИНЕНИЕ с таблицей целевого объекта строка с битой ссылкой будет полностью отфильтрована из результата выборки.Если необходимо программно проверить, является ли ссылка битой, рассмотрим два надежных способа:
1. Точечная проверка через легковесный запрос (рекомендуемый способ):
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| 1
|ИЗ
| Документ.ЗаказПоставщику КАК ЗаказПоставщику
|ГДЕ
| ЗаказПоставщику.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", ПроверяемаяСсылка);
ОбъектСуществует = НЕ Запрос.Выполнить().Пустой();
2. Поиск всех битых ссылок в таблице:
Для массового поиска записей с потерянными связями используется левое соединение с проверкой на NULL:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЗаказКлиента.Ссылка КАК ДокументИсточник,
| ЗаказКлиента.ЗаказПоставщику КАК НеразрешеннаяСсылка
|ИЗ
| Документ.ЗаказКлиента КАК ЗаказКлиента
| ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказПоставщику КАК ЗаказПоставщику
| ПО ЗаказКлиента.ЗаказПоставщику = ЗаказПоставщику.Ссылка
|ГДЕ
| ЗаказКлиента.ЗаказПоставщику <> ЗНАЧЕНИЕ(Документ.ЗаказПоставщику.ПустаяСсылка)
| И ЗаказПоставщику.Ссылка ЕСТЬ NULL";