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

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

В процессе разработки на платформе 1С:Предприятие часто возникает задача программного создания или поиска ссылок по их уникальным идентификаторам (GUID). Однако метод ПолучитьСсылку таит в себе важную техническую особенность: он не проверяет фактическое наличие записи в таблицах базы данных. В результате мы можем получить так называемую «битую ссылку», которая внешне выглядит как заполненная, но при попытке работы с ней возникают сложности.

В этой статье мы подробно разберем, как корректно определить, существует ли объект в базе, почему стандартные методы проверки могут подвести и какой способ является наиболее производительным.

Особенности метода ПолучитьСсылку и природа «битых» ссылок

Разберем ситуацию: когда мы вызываем метод Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор(ИдентификаторИзФайла)), система выполняет чисто математическую операцию преобразования строки (или объекта типа УникальныйИдентификатор) в типизированную ссылку 1С. В этот момент обращения к базе данных не происходит.

Если в базе данных нет записи с таким GUID, система все равно создаст объект ссылки. Проанализируем последствия:

Почему проверка через ПолучитьОбъект() неэффективна?

Часто начинающие разработчики пытаются проверить существование объекта следующим образом:


Номен = Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор(СтруктураАтрибутов.ref));
СпрОбъект = Номен.ПолучитьОбъект();

Если СпрОбъект <> Неопределено Тогда
    // Объект существует
КонецЕсли;

Проанализируем этот подход. Метод ПолучитьОбъект() выполняет полное чтение данных из базы. Если объект существует, 1С загрузит все его реквизиты и табличные части в оперативную память. Если ваша цель — просто убедиться в наличии записи, такой метод является крайне избыточным и медленным, особенно при массовой обработке данных. Если же объекта нет, метод вернет Неопределено, что технически решает задачу проверки, но ценой высокой нагрузки на сервер.

Оптимальный способ: Использование запроса

Самым быстрым и правильным способом проверки одной ссылки является выполнение легкого запроса. Мы обращаемся напрямую к таблице базы данных и проверяем наличие хотя бы одной записи с искомой ссылкой. Рассмотрим пример реализации:


// Сначала получаем ссылку по GUID
НоменСсылка = Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор(СтруктураАтрибутов.ref));

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

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

Если РезультатЗапроса.Пустой() Тогда
    // Объекта в базе нет. Можно создать новый или выдать ошибку.
    НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();
    НовыйЭлемент.УстановитьСсылкуНового(НоменСсылка);
    // ... заполнение реквизитов ...
    НовыйЭлемент.Записать();
Иначе
    // Объект существует, работаем с ним
    ОбъектНоменклатуры = НоменСсылка.ПолучитьОбъект();
КонецЕсли;

Важный момент: использование конструкции ВЫБРАТЬ ПЕРВЫЕ 1 и выбор только одного поля (например, самой ссылки или константы 1) минимизирует объем данных, передаваемых от сервера базы данных к серверу 1С.

Использование стандартных функций БСП

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


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

Использование готовой функции делает ваш код более читаемым и компактным. Вызов будет выглядеть так: Если ОбщегоНазначения.СсылкаСуществует(Номен) Тогда ....

Как обрабатывать большие списки ссылок?

Если вам нужно проверить не одну, а сотни или тысячи ссылок (например, при импорте номенклатуры из внешнего файла), категорически нельзя использовать запросы в цикле. Это приведет к значительной деградации производительности из-за множества обращений к СУБД (проблема N+1).

Разберем правильный алгоритм массовой проверки:

  1. Создадим таблицу значений, в которую поместим все наши GUID (или сформированные ссылки).
  2. Передадим эту таблицу в запрос в качестве параметра.
  3. В запросе выполним ЛЕВОЕ СОЕДИНЕНИЕ нашей временной таблицы с реальной таблицей справочника по полю Ссылка.
  4. Проанализируем результат: те строки, где поле из справочника равно NULL, соответствуют отсутствующим («битым») ссылкам.

Такой подход позволяет проверить тысячи записей одним-единственным запросом, что в сотни раз быстрее циклического перебора.

Резюме

Подведем итоги нашего анализа:

1. Метод ПолучитьСсылку никогда не возвращает Неопределено или пустую ссылку, если в него передан непустой GUID. Он просто «собирает» ссылку в памяти.

2. Проверки Пустая() и ЗначениеЗаполнено() бесполезны для выявления существования записи в БД, если ссылка была получена по GUID.

3. Запрос — самый надежный и быстрый инструмент проверки. Для одной ссылки используйте простой запрос или функции БСП, для списков — пакетную обработку с временными таблицами.

4. При создании новых объектов на основе внешних идентификаторов полезно использовать метод УстановитьСсылкуНового(), чтобы сохранить связь между системами и избежать дублей при повторных загрузках.

← На главную