В процессе разработки часто возникает задача, когда необходимо выполнить запрос к разным справочникам в зависимости от выбора пользователя на форме. Попытки передать Таблицу Значений ТЗ с типом справочника в качестве параметра запроса часто приводят к ошибкам вида «Поле не найдено» или проблемам с производительностью. Давайте разберем, почему так происходит и как реализовать это правильно.
Когда мы пытаемся передать ТЗ в запрос как источник данных, 1С воспринимает её как временный набор строк, лишенный метаданных. В результате при попытке обратиться к полям объекта через точку, например Статьи.Родитель.Код, система не может выполнить разыменование, так как в ТЗ хранятся лишь ссылки, а не структура метаданных. Кроме того, такой подход принуждает платформу выполнять неявные соединения с таблицами базы данных, что ведет к катастрофическому падению производительности и полному сканированию таблиц (Table Scan).
Самый эффективный способ — формирование текста запроса «на лету» с помощью подстановки строки. Вместо передачи сложной структуры данных, мы просто подставляем имя таблицы в текст запроса перед его выполнением. Рассмотрим это на примере.
Допустим, на форме есть список выбора с именами справочников. Мы можем использовать следующий алгоритм:
// Предположим, ВидСправочника содержит строку "СтатьиЗатрат"
ИмяСправочника = ЭтаФорма.ВидСправочника;
Родитель = Справочники[ИмяСправочника].НайтиПоКоду("БП-000001");
Запрос = Новый Запрос(
"ВЫБРАТЬ
| Т.Ссылка КАК Ссылка
|ИЗ
| Справочник.ШаблонСправочника КАК Т
|ГДЕ
| Т.Ссылка В ИЕРАРХИИ(&Родитель)
| И НЕ Т.ЭтоГруппа");
// Заменяем шаблонное имя на выбранное пользователем
Запрос.Текст = СтрЗаменить(Запрос.Текст, "ШаблонСправочника", ИмяСправочника);
Запрос.УстановитьПараметр("Родитель", Родитель);
Результат = Запрос.Выполнить().Выгрузить();
Этот метод позволяет оптимизатору СУБД корректно построить план выполнения запроса, используя существующие индексы, что обеспечивает высокую скорость работы даже на больших объемах данных.
Вместо того чтобы вручную перебирать всех родителей элемента через Статьи.Родитель.Родитель..., используйте штатный механизм платформы В ИЕРАРХИИ. Это не только делает код более чистым и универсальным для любой глубины вложенности, но и позволяет системе 1С задействовать оптимизированные внутренние механизмы поиска.
Для доступа к менеджерам справочников динамически мы используем конструкцию Справочники[ИмяСправочника]. Это избавляет нас от необходимости создавать лишние объекты в памяти и позволяет сразу получить ссылку на нужный элемент для передачи в параметр &Родитель.
СтатьиЗатрат, СтатьиДвиженияДенежныхСредств).Справочники[ИмяСправочника]).СтрЗаменить для подготовки текста запроса, чтобы не нарушать структуру SQL-команд.Таким образом, мы избегаем использования ПостроительЗапроса там, где он избыточен, и получаем быстродействующий код, который легко поддерживать и развивать. При таком подходе система всегда работает с конкретным типом данных, что исключает ошибки обращения к несуществующим полям.