Как использовать битую ссылку в условии запроса 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке механизмов интеграции, обменов данными через распределенные информационные базы (РИБ) или веб-сервисы разработчики часто сталкиваются с понятием «битой» (неразрешимой) ссылки. Такая ссылка представляет собой объект типа Ссылка, для которого в информационной базе отсутствует соответствующая запись в таблице объекта (в интерфейсе это отображается как «<Объект не найден>...»).

Рассмотрим, можно ли использовать такую ссылку в качестве условия фильтрации в запросе, почему возникают ошибки и как правильно передавать битую ссылку в параметры запроса.

Как СУБД обрабатывает битые ссылки в запросах

Разберем внутреннее устройство ссылочного типа данных. На уровне СУБД ссылочные реквизиты хранятся как 16-байтные бинарные идентификаторы (GUID). Когда в запросе выполняется простое прямое сравнение на равенство, например ГДЕ Документ.Реквизит = &Параметр, платформа 1С передает СУБД команду сравнить байты в колонке таблицы. При этом обращение к самой таблице отсутствующего объекта не происходит.

Это означает, что условие на равенство с битой ссылкой полноценно работает, если в параметр передана корректно сформированная ссылка нужного типа с тем же самым уникальным идентификатором.

Пошаговое получение и передача битой ссылки в запрос

Выясним причину частой ошибки: попытка передать в параметр строку вида "<Объект не найден>..." или строковое представление GUID приведет к пустому результату запроса, так как типы данных не совпадут. Передавать необходимо именно объект ссылочного типа.

Разберем по шагам, как получить ссылку по известному идентификатору и применить её в запросе:

  1. Преобразуем строковый GUID в объект УникальныйИдентификатор.
  2. Используем метод менеджера соответствующего объекта ПолучитьСсылку() для создания ссылки. Даже если объекта физически нет в базе, метод вернет валидную ссылку с указанным GUID.
  3. Устанавливаем полученную ссылку в качестве параметра запроса и выполняем выборку.

Посмотрим на пример кода:


// Строковый GUID битой ссылки (например, полученный из внешнего сервиса или пакета обмена)
СтрокаGUID = "a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d";

// 1. Создаем объект уникального идентификатора
Идентификатор = Новый УникальныйИдентификатор(СтрокаGUID);

// 2. Получаем ссылку через менеджер соответствующего метаданного
БитаяСсылка = Документы.ЗаказПоставщику.ПолучитьСсылку(Идентификатор);

// 3. Формируем и выполняем запрос
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ЗаказКлиента.Ссылка КАК Ссылка,
    |	ЗаказКлиента.Номер КАК Номер,
    |	ЗаказКлиента.Дата КАК Дата
    |ИЗ
    |	Документ.ЗаказКлиента КАК ЗаказКлиента
    |ГДЕ
    |	ЗаказКлиента.ЗаказПоставщику = &БитаяСсылка";

Запрос.УстановитьПараметр("БитаяСсылка", БитаяСсылка);
Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
    // Обработка найденных документов
КонецЦикла;

Подводные камни при работе с неразрешенными ссылками

Проанализируем ситуации, при которых запрос с битой ссылкой может вернуть непредвиденный результат или работать некорректно:

  1. Обращение через точку к реквизитам битой ссылки. Если в секции ВЫБРАТЬ или ГДЕ обратиться к реквизиту отсутствующего объекта (например, ЗаказПоставщику.Номер), платформа автоматически сформирует ЛЕВОЕ СОЕДИНЕНИЕ с таблицей отсутствующего объекта. Так как записи нет, результатом выражения всегда будет NULL.
  2. Использование соединений. При использовании ВНУТРЕННЕЕ СОЕДИНЕНИЕ с таблицей целевого объекта строка с битой ссылкой будет полностью отфильтрована из результата выборки.
  3. Составные типы данных. Если реквизит может содержать ссылки разных типов (например, документы разных видов), важно сформировать ссылку через правильный менеджер метаданных. В противном случае СУБД не сопоставит типы, и условие не выполнится.

Как проверить существование объекта в базе

Если необходимо программно проверить, является ли ссылка битой, рассмотрим два надежных способа:

1. Точечная проверка через легковесный запрос (рекомендуемый способ):


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |	1
    |ИЗ
    |	Документ.ЗаказПоставщику КАК ЗаказПоставщику
    |ГДЕ
    |	ЗаказПоставщику.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", ПроверяемаяСсылка);
ОбъектСуществует = НЕ Запрос.Выполнить().Пустой();

2. Поиск всех битых ссылок в таблице:

Для массового поиска записей с потерянными связями используется левое соединение с проверкой на NULL:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ЗаказКлиента.Ссылка КАК ДокументИсточник,
    |	ЗаказКлиента.ЗаказПоставщику КАК НеразрешеннаяСсылка
    |ИЗ
    |	Документ.ЗаказКлиента КАК ЗаказКлиента
    |	ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказПоставщику КАК ЗаказПоставщику
    |		ПО ЗаказКлиента.ЗаказПоставщику = ЗаказПоставщику.Ссылка
    |ГДЕ
    |	ЗаказКлиента.ЗаказПоставщику <> ЗНАЧЕНИЕ(Документ.ЗаказПоставщику.ПустаяСсылка)
    |	И ЗаказПоставщику.Ссылка ЕСТЬ NULL";
← На главную