Часто при разработке в 1С возникает необходимость не только выполнить пакетный запрос с созданием временных таблиц, но и получить содержимое этих таблиц для дальнейшей программной обработки или анализа — для этого есть инструмент для пошаговой отладки кода 1С. Проблема заключается в том, что стандартный метод ВыполнитьПакет при выполнении инструкций помещения данных возвращает лишь количество записей, а не саму таблицу значений. Рассмотрим подробнее, как обойти это ограничение и получить нужные данные, сохранив при этом производительность системы.
Начиная с версии платформы 1С 8.3.8, разработчикам доступен специальный метод, который изначально задумывался как мощный инструмент для отладки. Проанализируем ситуацию: если у вас есть пакетный запрос, создающий несколько временных таблиц, вы можете выполнить его методом ВыполнитьПакетСПромежуточнымиДанными().
Этот метод выполняет все запросы пакета и возвращает массив, в котором для каждой временной таблицы содержится её реальное содержимое. Посмотрим на пример кода:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ПОМЕСТИТЬ ВТ_Товары
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|;
|ВЫБРАТЬ
| Контрагенты.Ссылка КАК Ссылка
|ПОМЕСТИТЬ ВТ_Клиенты
|ИЗ
| Справочник.Контрагенты КАК Контрагенты";
МассивРезультатов = Запрос.ВыполнитьПакетСПромежуточнымиДанными();
ТаблицаТоваров = МассивРезультатов[0].Выгрузить(); // Содержимое ВТ_Товары
ТаблицаКлиентов = МассивРезультатов[1].Выгрузить(); // Содержимое ВТ_Клиенты
Важно: Данный метод перекачивает данные всех временных таблиц из СУБД в оперативную память сервера 1С. Если таблицы содержат сотни тысяч строк, это может привести к нехватке памяти (Out of Memory). Используйте его осторожно в рабочих механизмах, отдавая предпочтение точечной выгрузке данных.
Разберем по шагам альтернативный и более контролируемый вариант. Если вы не хотите нагружать сервер выгрузкой всех промежуточных данных, вы можете оставить стандартный метод ВыполнитьПакет(), но добавить в конец текста запроса отдельные инструкции на выборку нужных временных таблиц.
Этот способ позволяет точечно извлечь в результат пакета только то, что действительно необходимо бизнес-логике. Все данные читаются в рамках одного обращения к базе данных, что положительно сказывается на производительности и исключает грязное чтение.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Первая ИЗ Документ.РеализацияТоваровУслуг;
|
|ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Вторая ИЗ Справочник.Номенклатура;
|
|// Добавляем выборки в конец пакета
|ВЫБРАТЬ * ИЗ ВТ_Первая;
|ВЫБРАТЬ * ИЗ ВТ_Вторая;";
МассивПакет = Запрос.ВыполнитьПакет();
// Индексы 0 и 1 содержат количество помещенных записей
// Индексы 2 и 3 содержат реальные данные
ТЗ_Первая = МассивПакет[2].Выгрузить();
ТЗ_Вторая = МассивПакет[3].Выгрузить();
Выясним причину, почему многие разработчики используют объект МенеджерВременныхТаблиц. Если перед выполнением запроса вы инициализировали менеджер и передали его в запрос, временные таблицы физически остаются жить в базе данных в рамках сеанса этого менеджера, даже после выполнения пакета.
Мы вместе решаем задачу гибкого получения данных, поэтому давайте посмотрим, как вытащить содержимое любой таблицы напрямую через объектную модель менеджера, вообще не меняя текст пакетного запроса:
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст =
"ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Данные ИЗ Справочник.Склады";
Запрос.ВыполнитьПакет();
// Получаем данные напрямую из менеджера по имени ВТ
ВременнаяТаблица = Запрос.МенеджерВременныхТаблиц.Таблицы.Найти("ВТ_Данные");
Если ВременнаяТаблица <> Неопределено Тогда
ТЗ_Данные = ВременнаяТаблица.ПолучитьДанные().Выгрузить();
КонецЕсли;
Подведем итоги и систематизируем, какой способ лучше выбрать в зависимости от задачи:
ВыполнитьПакетСПромежуточнымиДанными().ВЫБРАТЬ * ИЗ ВТ_ИмяТаблицы в конец пакета и используйте обычный ВыполнитьПакет(). Это оптимально с точки зрения баланса производительности и потребления памяти.Запрос.МенеджерВременныхТаблиц.Таблицы.Найти(). Это позволит не засорять текст запроса служебными выборками.