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