Как проверить существование ссылки в базе данных 1С без метода ПолучитьОбъект

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

При обмене данными или интеграции систем часто возникает задача: проверить, существует ли уже элемент справочника или документ в базе-приемнике по полученному Уникальному Идентификатору (УИД/GUID). Если попытаться получить ссылку с помощью метода ПолучитьСсылку(УИД), платформа создаст объект типа «Ссылка» в оперативной памяти. При этом метод Ссылка.Пустая() всегда вернет Ложь, так как УИД зафиксирован, а проверка Ссылка.ПолучитьОбъект() = Неопределено считывает из СУБД абсолютно все реквизиты и табличные части объекта, что создает колоссальную избыточную нагрузку.

Рассмотрим подробно, почему метод ПолучитьОбъект() не подходит для простой проверки существования записи и какие способы являются наиболее правильными и производительными.

Выясним причину проблемы с проверкой битых ссылок

Разберем, как платформа 1С работает со ссылками в памяти. Когда мы восстанавливаем ссылку по УИД, платформа еще не знает, есть ли соответствующая строка в базе данных СУБД. Проверка физического наличия записи происходит только при попытке обратиться к данным этой ссылки.

Использование метода ПолучитьОбъект() для проверки существования имеет следующие негативные последствия:

  1. Считывание всех данных: СУБД выполняет выборку всех реквизитов объекта, включая тяжелые табличные части и хранилища значений.
  2. Избыточный расход памяти: На сервере приложений создается полноценный объект 1С со всеми его данными, хотя нам требовался лишь флаговый ответ «да» или «нет».
  3. Падение производительности в циклах: При обработке больших массивов данных или рекурсивной загрузке связанных справочников метод вызывает сильные задержки.

Решение 1. Точечная проверка через запрос к СУБД

Самый простой и эффективный способ проверить, существует ли ссылка в СУБД — выполнить легкий запрос к таблице соответствующего объекта. В запросе выбираем только одно системное поле (например, Ссылка) или константу.

Проанализируем пример кода с запросом:


Функция СсылкаСуществуетВБазе(СсылкаПроверки) Экспорт

    ТекстЗапроса = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |    1 КАК Флаг
    |ИЗ
    |    " + СсылкаПроверки.Метаданные().ПолноеИмя() + " КАК Таблица
    |ГДЕ
    |    Таблица.Ссылка = &Ссылка";

    Запрос = Новый Запрос(ТекстЗапроса);
    Запрос.УстановитьПараметр("Ссылка", СсылкаПроверки);

    Возврат НЕ Запрос.Выполнить().Пустой();

КонецФункции

Этот способ выполняет минимальный по объему запрос к базе данных, проверяет только индексированное поле Ссылка и не считывает табличные части или реквизиты объекта.

Решение 2. Использование готовой функции из Библиотеки Стандартных Подсистем (БСП)

Если ваша конфигурация разработана на базе БСП (например, «Управление торговлей», «ERP», «Бухгалтерия предприятия»), нет необходимости писать собственный код. В составе БСП уже есть готовая функция ОбщегоНазначенияКлиентСервер.СсылкаСуществует() или ОбщегоНазначения.СсылкаСуществует().

Рассмотрим, как реализована эта функция внутри БСП:


Функция СсылкаСуществует(ЛюбаяСсылка) Экспорт
    
    ТекстЗапроса = "
    |ВЫБРАТЬ
    |    Ссылка КАК Ссылка
    |ИЗ
    |    [ИмяТаблицы]
    |ГДЕ
    |    Ссылка = &Ссылка
    |";
    
    ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "[ИмяТаблицы]", ЛюбаяСсылка.Метаданные().ПолноеИмя());
    
    Запрос = Новый Запрос;
    Запрос.Текст = ТекстЗапроса;
    Запрос.УстановитьПараметр("Ссылка", ЛюбаяСсылка);
    
    Возврат НЕ Запрос.Выполнить().Пустой();
    
КонецФункции

Решение 3. Пакетная проверка массива ссылок и кэширование

Если проверка выполняется внутри цикла по загрузке множества элементов, одиночные запросы в цикле все равно будут замедлять работу из-за частых обращений к СУБД. В таких случаях следует применить два архитектурных подхода:

  1. Кэширование проверенных ссылок: Сохраняйте результат проверки в объект Соответствие, где ключом выступает УИД источника, а значением — полученная ссылка приемника или булево значение. При повторном обращении к этому УИД данные берутся из памяти без вызова запроса.
  2. Пакетный запрос: Соберите массив всех проверяемых ссылок, передайте его во временную таблицу запроса и выполните соединение с основной таблицей объекта. Это позволит за один запрос определить статус существования для тысяч элементов.

Посмотрим на пример пакетного запроса для проверки списка ссылок:


Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|    СписокСсылок.Ссылка КАК Ссылка,
|    ВЫБОР
|        КОГДА ТаблицаБД.Ссылка ИСХОДНО НЕ NULL ТОГДА ИСТИНА
|        ИНАЧЕ ЛОЖЬ
|    КОНЕЦ КАК Существует
|ИЗ
|    &ТаблицаСсылок КАК СписокСсылок
|    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК ТаблицаБД
|    ПО СписокСсылок.Ссылка = ТаблицаБД.Ссылка";

Запрос.УстановитьПараметр("ТаблицаСсылок", МассивПроверяемыхСсылок);
Результат = Запрос.Выполнить().Выгрузить();

Подводя итог: для разовой проверки отдельной ссылки используйте запрос к полю Ссылка или функцию БСП. Для массовых операций и оптимизации обменов объединяйте проверки в один пакетный запрос и используйте локальный кэш в виде Соответствие.

← На главную