К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как найти элемент справочника по ссылке в 1С

Разбираем способы найти элемент справочника по ссылке в 1С: методы ПолучитьОбъект, запросы, проверка битых ссылок, типичные ошибки и примеры кода.

Ссылка в 1С — это уникальный идентификатор объекта базы данных, который позволяет однозначно указать на конкретный элемент справочника, документ или другой объект. Задача найти элемент справочника по ссылке возникает постоянно: при обмене данными, при обработке загруженных файлов, при восстановлении связей между объектами и при отладке. В отличие от поиска по коду или наименованию, поиск по ссылке работает быстро и гарантированно однозначен, потому что ссылка уникальна в пределах всей информационной базы.

Важно понимать разницу между ссылкой и объектом. Ссылка — это «указатель», лёгкая структура, которая хранит только идентификатор и тип. Объект — это полноценная загруженная в память копия данных элемента, которую можно изменять и записывать. Получить объект из ссылки можно в любой момент, но для многих задач достаточно самой ссылки или данных, прочитанных через запрос без загрузки объекта целиком.

Ниже разобраны основные способы найти элемент справочника по ссылке: через методы встроенного языка, через запрос, через проверку существования элемента и через универсальные инструменты в режиме предприятия. Для каждого способа указаны условия применения, ограничения и типичные ошибки.

Что такое ссылка и как проверить её корректность

Ссылка формируется платформой автоматически при создании объекта и состоит из уникального идентификатора (GUID) и указания на тип объекта. Программно тип ссылки проверяется функцией ТипЗнч(), а принадлежность к справочникам — через метаданные:

Если Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(МояСсылка)) Тогда

// это ссылка на элемент какого-то справочника

КонецЕсли;

Перед тем как искать элемент по ссылке, убедитесь, что ссылка заполнена. Пустая ссылка — это не «отсутствие ссылки», а вполне конкретное значение с нулевым идентификатором, и попытка работать с ней как с реальным элементом приведёт к ошибкам логики. Проверка выполняется методом Пустая() или сравнением с пустой ссылкой конкретного справочника:

Если МояСсылка.Пустая() Тогда

Возврат; // искать нечего

КонецЕсли;

Отдельная ситуация — битая ссылка. Она возникает, когда элемент удалили непосредственно (без контроля ссылочной целостности) или при обмене данными объект-владелец пришёл раньше объекта, на который ссылается. Определить битую ссылку можно по строковому представлению: Строка(МояСсылка) вернёт текст вида «<Объект не найден> (…)». Программный способ надёжнее — запросом проверить, есть ли элемент с такой ссылкой в таблице.

Получение объекта методом ПолучитьОбъект

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

ЭлементОбъект = МояСсылка.ПолучитьОбъект();

Если ЭлементОбъект = Неопределено Тогда

// элемент удалён — ссылка битая

Иначе

Наименование = ЭлементОбъект.Наименование;

КонецЕсли;

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

Поиск элемента запросом

Когда нужно проверить существование элемента или прочитать несколько его полей без загрузки объекта, оптимален запрос. Условие по ссылке записывается напрямую — поле «Ссылка» есть у каждой таблицы справочника:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Номенклатура.Код,

| Номенклатура.Наименование,

| Номенклатура.ПометкаУдаления

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

| Номенклатура.Ссылка = &Ссылка";

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

Результат = Запрос.Выполнить();

Если Результат.Пустой() Тогда

// элемента с такой ссылкой нет

Иначе

Выборка = Результат.Выбрать();

Выборка.Следующий();

// данные доступны через Выборка.Код и т.д.

КонецЕсли;

Запрос решает сразу две задачи: проверяет существование элемента (пустой результат = битая ссылка) и возвращает нужные реквизиты одним обращением к базе. Это предпочтительный способ в обработках обмена, отчётах и любых массовых операциях. Дополнительное преимущество — запрос не создаёт объект в памяти и не накладывает блокировок на запись.

Способы найти элемент по ссылке

Ссылка.ПолучитьОбъект()

Подходит, когда элемент нужно изменить и записать. Минус — загружает объект целиком и медленен в циклах.

Чтение реквизита через ссылку

Удобно для одного-двух полей в разовой логике. Минус — каждое обращение к реквизиту идёт в базу отдельно.

Запрос с условием по ссылке

Оптимален для проверки существования и массового чтения. Минус — данные только для чтения, изменить элемент через запрос нельзя.

Проверка существования элемента и работа с битыми ссылками

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

Безопасная проверка ссылки
  1. 1
    Проверьте, что ссылка не пустая: МояСсылка.Пустая().
  2. 2
    Убедитесь, что тип ссылки соответствует ожидаемому справочнику через ТипЗнч().
  3. 3
    Выполните запрос с условием Ссылка = &Ссылка или вызовите ПолучитьОбъект().
  4. 4
    Если результат пустой или Неопределено — зафиксируйте битую ссылку в журнале и не используйте её данные.
  5. 5
    Если элемент найден — читайте реквизиты или изменяйте объект по логике задачи.

Битые ссылки нельзя «восстановить» программным поиском — объект уже удалён. Варианты действий: найти в резервной копии, создать новый элемент с тем же уникальным идентификатором (метод ПолучитьСсылку(Новый УникальныйИдентификатор(...)) с последующим созданием объекта по этой ссылке) или очистить битые ссылки в базе штатной обработкой тестирования и исправления. Последний вариант применяйте осознанно: очистка необратима, и сначала стоит выгрузить список всех битых ссылок для анализа.

Обратная задача: получить ссылку по известному идентификатору

На практике часто встречается смежная ситуация: из внешней системы пришёл не объект ссылки, а строка с GUID. Тогда ссылку сначала конструируют, а потом уже ищут по ней элемент:

УИД = Новый УникальныйИдентификатор(СтрокаGUID);

НайденнаяСсылка = Справочники.Номенклатура.ПолучитьСсылку(УИД);

// далее — проверка существования запросом или ПолучитьОбъект()

Обратите внимание: ПолучитьСсылку() сам по себе не ищет ничего в базе — он только формирует значение ссылки из идентификатора. Элемент с таким идентификатором может существовать, а может и нет, поэтому проверка существования обязательна. Типичная ошибка — считать, что раз ссылка получена, элемент есть, и сразу читать его реквизиты.

Поиск элемента в режиме предприятия без программирования

Если вы не разработчик, а пользователь, которому известна ссылка (например, из сообщения об ошибке или из обмена), найти элемент можно штатными средствами. Во многих конфигурациях доступны функции «Поиск ссылок на объект» и «Поиск и удаление дублей», а универсальный путь — команда «Все функции» → «Стандартные» → обработки поиска. Если известен уникальный идентификатор, его можно подставить в навигационную ссылку вида e1cib/data/Справочник.Номенклатура?ref=... и открыть элемент напрямую в клиенте.

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

Типичные ошибки
01
Чтение реквизитов ссылки без проверки существования — при битой ссылке получаете «Объект не найден» в данных отчёта или обмена.
02
Вызов ПолучитьОбъект() в цикле по большой выборке — резкое падение производительности и лишние блокировки.
03
Сравнение ссылок строковым представлением вместо оператора равенства — строки могут совпадать у разных типов, а сравнение ссылок надёжнее и быстрее.
04
Путаница между ПолучитьСсылку() и поиском: метод только конструирует ссылку, но не гарантирует наличие элемента в базе.
05
Игнорирование пометки удаления: найденный элемент может быть помечен на удаление, и использовать его в новых документах не следует.

Производительность и ограничения

Поиск по ссылке — самая быстрая из возможных операций поиска, потому что ссылка является ключом таблицы и поиск идёт по кластерному индексу. Тем не менее архитектура кода имеет значение: тысяча отдельных обращений ПолучитьОбъект() всегда проиграет одному запросу с условием «Ссылка В (&СписокСсылок)». В массовых обработках собирайте ссылки в массив или таблицу значений и выбирайте данные пакетно.

Помните и о правах доступа. Если у пользователя, под которым выполняется код, нет прав на чтение справочника, обращение к данным вызовет ошибку нарушения прав. В серверных процедурах, где это осознанно нужно, используйте привилегированный режим (УстановитьПривилегированныйРежим(Истина)), но не злоупотребляйте им — он отключает проверку прав и RLS для всего кода внутри.

Итог

Что важно запомнить

Для чтения и изменения элемента используйте ПолучитьОбъект() с обязательной проверкой на Неопределено. Для проверки существования и массового чтения — запрос с условием по ссылке. Всегда проверяйте ссылку на пустоту и битость перед работой с данными.

Частые вопросы

Чем ссылка отличается от объекта справочника?

Ссылка — компактный идентификатор, который только указывает на элемент. Объект — загруженная в память копия данных, которую можно изменять и записывать. Для чтения одного поля достаточно ссылки, для изменения данных нужен объект.

Как понять, что ссылка битая?

Строковое представление такой ссылки содержит текст «Объект не найден». Программно надёжнее выполнить запрос с условием по ссылке: пустой результат означает, что элемента в базе нет. Метод ПолучитьОбъект() в этом случае вернёт Неопределено.

Можно ли найти элемент, если известен только GUID в виде строки?

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

Что быстрее: ПолучитьОбъект или запрос?

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

Найденный элемент помечен на удаление — можно ли его использовать?

Технически можно: пометка удаления не мешает читать данные. Но подставлять такой элемент в новые документы не следует — при снятии контроля это создаст проблемы при удалении помеченных объектов. Лучше найти или создать актуальный элемент.

Как найти все места, где используется ссылка?

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