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