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