← Назад к вопросам

Как получить значение реквизита от ссылки?

1.3 Junior🔥 101 комментариев
#Запросы и оптимизация#Стандарты разработки

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Получение значения реквизита от ссылки в 1С

Это базовая операция — ссылка это указатель, а не сами данные. Существует несколько подходов в зависимости от контекста и производительности.

1. Простой способ: Загрузить объект

// Если у нас есть ссылка на справочник
СсылкаНаКонтрагента = Справочники.Контрагенты.НайтиПоКоду("К001");

// Получить объект и прочитать реквизит
Объект = СсылкаНаКонтрагента.ПолучитьОбъект();
НаименованиеКонтрагента = Объект.Наименование;
ИНН = Объект.ИНН;

Минусы:

  • Медленно (загружаем весь объект)
  • Если объект удалён — будет исключение
  • Избыточно если нужна одна колонка

2. Прямое обращение к реквизиту (платформа 8.3.10+)

// Новый способ — прямой доступ к реквизитам через ссылку
Наименование = СсылкаНаКонтрагента.Наименование;
ИНН = СсылкаНаКонтрагента.ИНН;

Плюсы:

  • Быстро (не загружаем объект)
  • Чистый синтаксис
  • Работает если объект был удалён (даёт пустоту)

Минусы:

  • Только на 8.3.10+ версиях
  • Не работает для табличных частей

3. Запрос через SQL (самый оптимальный)

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

Почему это быстро:

  • Запрос идёт прямо в БД
  • Не загружаем весь объект
  • Можно выбрать только нужные колонки
  • СУБД делает оптимизацию

4. Использование таблицы значений (кеширование)

Когда нужно много раз обратиться к одним данным:

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

5. Обработка удалённых ссылок

Если справочник был удалён:

Процедура БезопасноПолучитьДанные(СсылкаКонтрагента) Экспорт
    
    // Способ 1: Проверить существование
    Если СсылкаКонтрагента.Пусто() Или НЕ СсылкаКонтрагента.ПолучитьОбъект() <> Неопределено Тогда
        // Справочник удалён
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = "Контрагент удалён из системы";
        Сообщение.Сообщить();
        Возврат;
    КонецЕсли;
    
    // Способ 2: Через запрос (безопаснее)
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ 1
        |    1
        |ИЗ
        |    Справочник.Контрагенты
        |ГДЕ
        |    Ссылка = &Ссылка";
    
    Запрос.УстановитьПараметр("Ссылка", СсылкаКонтрагента);
    
    Если Запрос.Выполнить().Пусто() Тогда
        // Справочник удалён — получаем пустоту, не ошибку
        ИМЯ = "Удалённый справочник";
    КонецЕсли;
    
КонецПроцедуры;

6. Практический пример: Получение данных в цикле

// ❌ ПЛОХО — N+1 проблема (запрос в цикле)
Для Каждого Документ Из ДокументыДляОбработки Цикл
    Объект = Документ.ПолучитьОбъект(); // Запрос за каждой строкой!
    Наименование = Объект.Контрагент.Наименование;
КонецЦикла;
// Результат: 1000 документов = 1001 запрос!

// ✅ ХОРОШО — один запрос на всё
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    Документы.Ссылка,
    |    Контрагенты.Наименование,
    |    Контрагенты.ИНН
    |ИЗ
    |    Документ.Счёт КАК Документы
    |ВНУТРЕННЕЕ СОЕДИНЕНИЕ
    |    Справочник.Контрагенты КАК Контрагенты
    |    ПО Документы.Контрагент = Контрагенты.Ссылка";

Таблица = Запрос.Выполнить().Выгрузить();

Для Каждого Строка Из Таблица Цикл
    Наименование = Строка.Наименование; // Из памяти, мгновенно
КонецЦикла;
// Результат: 1 запрос, обрабатываем в памяти

Рекомендации по производительности

  1. Если нужно одно значение → используй 8.3.10+ синтаксис или прямой доступ
  2. Если нужно несколько значений → запрос
  3. Если в цикле → один запрос + таблица значений
  4. Если ссылка может быть удалена → проверь через запрос (не через объект)
  5. Если часто обращаешься → кешируй в памяти (Новая ТаблицаЗначений)

Вывод: Выбирай метод по контексту. Запрос обычно быстрее загрузки объекта, особенно в циклах. Один запрос на группу ссылок лучше N запросов в цикле.

Как получить значение реквизита от ссылки? | PrepBro