Как правильно получить дополнительные свойства контрагента через запрос в 1С?

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

При разработке отчетов, обработок или заполнении реквизитов печатных форм часто требуется программно извлечь значения дополнительных реквизитов и сведений. Типичная проблема, с которой сталкиваются разработчики, — запрос к регистру сведений РегистрСведений.ЗначенияСвойствОбъектов возвращает значение NULL, либо запрос работает крайне неэффективно из-за избыточных вложенных конструкций.

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

Почему запрос возвращает NULL и как устроена типичная ошибка

Проанализируем исходную структуру запроса. Частая ошибка заключается в использовании вложенных подзапросов в секции ЛЕВОЕ СОЕДИНЕНИЕ для каждого отдельного свойства, а также в передаче некорректных параметров:

  1. Передача строк вместо ссылок на свойства: Измерение Свойство в регистре типизировано ссылкой на план видов характеристик (например, ПланыВидовХарактеристик.СвойстваОбъектов или ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения). Если в параметры &ДатаДекларации и &ДекларацияСоответствия передано строковое наименование, а не ссылка, соединение не найдет совпадений и вернет NULL.
  2. Перезапись переменных в цикле: Если переменные, в которых хранятся ссылки на свойства, перезаписываются значениями выборки внутри цикла, то при повторном запуске запроса в параметры попадут пустые данные или NULL.
  3. Неэффективные вложенные запросы: Создание подзапросов в секциях ЛЕВОЕ СОЕДИНЕНИЕ заставляет СУБД сначала формировать временные таблицы по всем записям регистра с указанным свойством, а затем соединять их с основной таблицей, что создает избыточную нагрузку.

Вариант 1. Прямое соединение с регистром сведений без подзапросов

Рассмотрим правильное построение запроса при необходимости получить фиксированный набор свойств для контрагента. Условие по конкретному свойству следует выносить непосредственно в секцию ПО левого соединения, а для обработки отсутствующих значений использовать функцию ЕСТЬNULL.

Посмотрим на пример корректного запроса:


ВЫБРАТЬ
    Контрагенты.Ссылка КАК Ссылка,
    Контрагенты.Наименование КАК Наименование,
    ЕСТЬNULL(СвойствоДекларация.Значение, "") КАК ДекларацияСоответствия,
    ЕСТЬNULL(СвойствоДата.Значение, ДАТАВРЕМЯ(1, 1, 1)) КАК ДатаДекларации
ИЗ
    Справочник.Контрагенты КАК Контрагенты
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияСвойствОбъектов КАК СвойствоДекларация
        ПО Контрагенты.Ссылка = СвойствоДекларация.Объект
        И СвойствоДекларация.Свойство = &ДекларацияСоответствия
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияСвойствОбъектов КАК СвойствоДата
        ПО Контрагенты.Ссылка = СвойствоДата.Объект
        И СвойствоДата.Свойство = &ДатаДекларации
ГДЕ
    Контрагенты.Ссылка = &ОсновнойПоставщик

Разберем по шагам, как правильно подготовить параметры и выполнить выборку на встроенном языке:


Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|    Контрагенты.Ссылка КАК Ссылка,
|    ЕСТЬNULL(СвойствоДекларация.Значение, """") КАК ДекларацияСоответствия,
|    ЕСТЬNULL(СвойствоДата.Значение, ДАТАВРЕМЯ(1, 1, 1)) КАК ДатаДекларации
|ИЗ
|    Справочник.Контрагенты КАК Контрагенты
|    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияСвойствОбъектов КАК СвойствоДекларация
|        ПО Контрагенты.Ссылка = СвойствоДекларация.Объект
|        И СвойствоДекларация.Свойство = &ДекларацияСоответствия
|    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияСвойствОбъектов КАК СвойствоДата
|        ПО Контрагенты.Ссылка = СвойствоДата.Объект
|        И СвойствоДата.Свойство = &ДатаДекларации
|ГДЕ
|    Контрагенты.Ссылка = &ОсновнойПоставщик";

// Получаем правильные ссылки на свойства
СсылкаСвойствоДекларация = ПланыВидовХарактеристик.СвойстваОбъектов.НайтиПоНаименованию("Декларация соответствия");
СсылкаСвойствоДата = ПланыВидовХарактеристик.СвойстваОбъектов.НайтиПоНаименованию("Дата декларации");

Запрос.УстановитьПараметр("ОсновнойПоставщик", Текстр.Товар.ОсновнойПоставщик);
Запрос.УстановитьПараметр("ДекларацияСоответствия", СсылкаСвойствоДекларация);
Запрос.УстановитьПараметр("ДатаДекларации", СсылкаСвойствоДата);

Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
    СтруктураВозврата = Новый Структура;
    СтруктураВозврата.Вставить("Ссылка", Выборка.Ссылка);
    СтруктураВозврата.Вставить("ДекларацияСоответствия", Выборка.ДекларацияСоответствия);
    СтруктураВозврата.Вставить("ДатаДекларации", Выборка.ДатаДекларации);
КонецЕсли;

Вариант 2. Прямая выборка всех свойств контрагента из регистра

Если ссылка на контрагента уже известна и нужно просто прочитать его свойства, можно обойтись без соединения со справочником Справочник.Контрагенты. Достаточно обратиться напрямую к регистру сведений РегистрСведений.ЗначенияСвойствОбъектов с отбором по объекту.

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


Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|    ЗначенияСвойств.Свойство КАК Свойство,
|    ЗначенияСвойств.Значение КАК Значение
|ИЗ
|    РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойств
|ГДЕ
|    ЗначенияСвойств.Объект = &Контрагент
|    И ЗначенияСвойств.Свойство В(&СписокСвойств)";

СписокСвойств = Новый Массив;
СписокСвойств.Добавить(СсылкаСвойствоДекларация);
СписокСвойств.Добавить(СсылкаСвойствоДата);

Запрос.УстановитьПараметр("Контрагент", Текстр.Товар.ОсновнойПоставщик);
Запрос.УстановитьПараметр("СписокСвойств", СписокСвойств);

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    Если Выборка.Свойство = СсылкаСвойствоДекларация Тогда
        ЗначениеДекларация = Выборка.Значение;
    ИначеЕсли Выборка.Свойство = СсылкаСвойствоДата Тогда
        ЗначениеДата = Выборка.Значение;
    КонецЕсли;
КонецЦикла;

Важные практические рекомендации

  1. Проверяйте хранение свойств в конфигурации: В современных типовых конфигурациях на базе БСП (УТ 11, КА 2, ERP, БП 3.0) дополнительные реквизиты хранятся в табличной части ДополнительныеРеквизиты самих объектов, а в регистре сведений сохраняются только дополнительные сведения.
  2. Используйте методы БСП при их наличии: Если конфигурация поддерживает Библиотеку стандартных подсистем, вместо написания прямых запросов рекомендуется использовать функции общего модуля УправлениеСвойствами, которые автоматически учитывают формат хранения и права доступа.
  3. Контролируйте типы параметров: Перед установкой параметров запроса всегда проверяйте, что ссылка на элемент плана видов характеристик найдена и заполнена с помощью функции ЗначениеЗаполнено().
← На главную