При разработке сложных отчетов или механизмов поиска связей между объектами программисты часто сталкиваются с необходимостью получить данные по нескольким документам сразу. Стандартный механизм Критерии отбора в 1С:Предприятие 8 предоставляет удобную виртуальную таблицу КритерийОтбора.СвязанныеДокументы. Однако при попытке передать в её параметр массив или список значений разработчик неизбежно сталкивается с ошибкой платформы. В этой статье мы подробно разберем, почему существует это ограничение и как его корректно обойти, сохранив производительность системы.
Для начала выясним причину, по которой платформа не позволяет передать массив в параметр &ЗначениеСвязи. Виртуальная таблица критерия отбора на уровне СУБД не является отдельной физической таблицей. Когда мы пишем запрос к КритерийОтбора.СвязанныеДокументы(&Документ), платформа 1С трансформирует его в сложную конструкцию UNION ALL (объединение), собирая данные из всех таблиц, которые входят в состав этого критерия.
Если бы платформа поддерживала передачу массива, ей пришлось бы динамически генерировать условия ГДЕ ... В (&Массив) для каждого входящего в состав объекта. На текущий момент архитектура запросов к виртуальным таблицам критериев отбора в 1С жестко ориентирована на поиск связей «от одного конкретного объекта». Передача списка значений (объектов разных типов) значительно усложнила бы генерацию SQL-кода и план выполнения запроса на стороне сервера базы данных.
Если перед нами стоит задача получить связанные документы не для одного, а для целого списка ссылок (например, для всех строк табличной части или результата другого запроса), наиболее эффективным способом будет самостоятельная сборка текста запроса. Рассмотрим подробнее, как это реализовать, используя метаданные системы.
Вместо того чтобы пытаться заставить критерий отбора работать с массивом, мы можем программно перебрать его состав. В объекте метаданных КритерииОтбора есть коллекция Состав, которая содержит все реквизиты всех объектов, участвующих в поиске. Проанализируем ситуацию на примере кода:
// Создаем массив ссылок, по которым нужно найти связи
МассивСсылок = Новый Массив;
МассивСсылок.Добавить(СсылкаНаДокумент1);
МассивСсылок.Добавить(СсылкаНаДокумент2);
// Инициализируем построитель текста запроса
ТекстЗапроса = "";
ПервыйОбход = Истина;
// Обращаемся к метаданным конкретного критерия отбора
КритерийМетаданные = Метаданные.КритерииОтбора.СвязанныеДокументы;
Для Каждого ЭлементСостава Из КритерийМетаданные.Состав Цикл
// Получаем полное имя реквизита (например, Документ.РеализацияТоваровУслуг.Реквизит.ДокументОснование)
ПолныйПуть = ЭлементСостава.ПолноеИмя();
// Вычленяем имя таблицы и имя поля
ЧастиПути = СтрРазделить(ПолныйПуть, ".");
ИмяТаблицы = ЧастиПути[0] + "." + ЧастиПути[1];
ИмяПоля = ЧастиПути[3];
Если Не ПервыйОбход Тогда
ТекстЗапроса = ТекстЗапроса + "
|ОБЪЕДИНИТЬ ВСЕ
|";
КонецЕсли;
// Формируем фрагмент запроса для конкретного типа документа
ТекстЗапроса = ТекстЗапроса + "
|ВЫБРАТЬ
| Т.Ссылка КАК Ссылка
|ИЗ
| " + ИмяТаблицы + " КАК Т
|ГДЕ
| Т." + ИмяПоля + " В (&МассивСсылок)";
ПервыйОбход = Ложь;
КонецЦикла;
Запрос = Новый Запрос(ТекстЗапроса);
Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
Результат = Запрос.Выполнить().Выгрузить();
Разберем, почему этот метод лучше, чем выполнение запроса в цикле или другие «костыльные» методы:
В современных конфигурациях, таких как 1С:ERP, Управление торговлей 11 или Бухгалтерия предприятия 3.0, разработчики часто используют механизмы Библиотеки стандартных подсистем (БСП). Выясним, как это влияет на нашу задачу. В некоторых случаях информация о связях дублируется в специальных регистрах сведений (например, СвязиОбъектов).
Если в вашей конфигурации внедрена подсистема «Связи объектов», рекомендуем проверить наличие соответствующего регистра. Работа с регистром сведений через стандартный запрос с условием В (&Массив) гораздо проще и не требует динамической сборки текста по метаданным. Однако стоит помнить, что данные в регистры могут записываться с задержкой или при определенных условиях, в то время как критерий отбора всегда возвращает актуальные данные на основе структуры базы данных.
Посмотрим на ситуацию со стороны отчетов. В СКД также нельзя передать массив в параметр виртуальной таблицы критерия. Если вам нужно построить отчет по связям для списка документов, используйте механизм Набор данных - запрос, в котором текст формируется программно перед выводом отчета. Для этого можно использовать обработчик ПриКомпоновкеРезультата в модуле объекта отчета, где вы сможете подменить текст запроса основной схемы компоновки данных на сформированный вышеуказанным способом код UNION ALL.
Подводя итог, можно сказать, что ограничение на передачу массива в критерий отбора — это не ошибка, а особенность реализации платформы. Для решения задачи мы рекомендуем:
Метаданные для автоматической сборки текста запроса, чтобы ваш код оставался универсальным при изменении состава критерия в будущем.Такой системный подход позволит вам эффективно работать со связанными документами, сохраняя высокую скорость работы системы даже при обработке больших массивов данных.