Почему временные таблицы в запросе пустые и как увидеть их содержимое?

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

Работа с временными таблицами (ВТ) — это фундаментальный навык оптимизации запросов в системе 1С:Предприятие 8. Однако начинающие разработчики часто сталкиваются с ситуацией, когда при отладке или попытке получить данные из созданной таблицы они видят пустой результат или вовсе не находят таблицу. Разберем по шагам, как устроены временные таблицы, почему свойство ВременныеТаблицыЗапроса может вводить в заблуждение и как правильно организовать работу с менеджером временных таблиц.

Понимание жизненного цикла временных таблиц

Проанализируем базовый механизм. Временная таблица — это объект, который физически создается в базе данных (в СУБД это чаще всего база tempdb). Существует два основных сценария её «жизни»:

  1. В рамках одного вызова Выполнить(): Если вы создаете ВТ внутри пакета запросов и не используете внешний менеджер, таблица существует ровно столько времени, сколько выполняется метод. Как только управление возвращается в код 1С, таблица в СУБД уничтожается.
  2. С использованием объекта МенеджерВременныхТаблиц: В этом случае время жизни ВТ привязывается к жизни объекта менеджера в памяти сервера 1С. Пока жив объект или пока не вызван метод Закрыть(), данные остаются доступными для последующих запросов.

Выясним причину, по которой данные не видны в отладчике. Если мы просто написали запрос с конструкцией ПОМЕСТИТЬ, но не инициализировали МенеджерВременныхТаблиц, то после выполнения строки Запрос.Выполнить() обращаться к таблицам уже поздно — их больше нет.

Правильная инициализация менеджера временных таблиц

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


Запрос = Новый Запрос;
// Назначаем новый менеджер напрямую свойству запроса
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;

Запрос.Текст = 
    "ВЫБРАТЬ
    |   1 КАК ЧисловоеПоле,
    |   ""Текст"" КАК ТекстовоеПоле
    |ПОМЕСТИТЬ ВТ_Тестовая
    |;
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |   *
    |ИЗ
    |   ВТ_Тестовая КАК ВТ_Тестовая";

РезультатЗапроса = Запрос.Выполнить();

Обратим внимание на важный нюанс: создание отдельной переменной для менеджера (например, МВТ = Новый МенеджерВременныхТаблиц) оправдано только в том случае, если вы планируете передавать этот менеджер в другие процедуры или назначать его разным объектам Запрос. Если же менеджер нужен только для текущего блока кода, прямое присвоение Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц выглядит чище и избавляет от лишних ссылок в памяти.

Как увидеть содержимое ВТ в режиме отладки

Часто программисты пытаются найти данные в свойстве Запрос.ВременныеТаблицыЗапроса. Проанализируем это свойство: на самом деле оно является служебным и содержит лишь описание структуры таблиц, а не их строки. Чтобы действительно увидеть данные «здесь и сейчас» при остановке в отладчике, воспользуемся следующими приемами.

Способ 1. Использование ВыполнитьПакетСПромежуточнымиДанными(). Это самый мощный инструмент для отладки. Вместо обычного метода Выполнить(), который возвращает результат только последней выборки, этот метод возвращает массив результатов всех запросов пакета, включая содержимое всех созданных ВТ.


// В табло отладчика или в коде для тестирования
МассивРезультатов = Запрос.ВыполнитьПакетСПромежуточнымиДанными();
// Теперь в МассивРезультатов[0] будут данные первой ВТ, в [1] — второй и т.д.

Важно: Не используйте этот метод в рабочем коде для обработки огромных массивов данных (сотни тысяч строк), так как это заставляет сервер 1С выкачивать абсолютно все данные из СУБД в оперативную память, что может привести к существенному замедлению системы.

Способ 2. Программная выгрузка из менеджера. Если у запроса установлен менеджер, мы можем в любой момент обратиться к нему и выгрузить данные конкретной таблицы в ТаблицуЗначений. Рассмотрим пример:


КоличествоТаблиц = Запрос.МенеджерВременныхТаблиц.Таблицы.Количество();
Сообщить("Всего временных таблиц: " + КоличествоТаблиц);

// Выгружаем данные первой таблицы по индексу
ДанныеВТ = Запрос.МенеджерВременныхТаблиц.Таблицы[0].ПолучитьДанные().Выгрузить();

// Или находим таблицу по имени
ТаблицаПоИмени = Запрос.МенеджерВременныхТаблиц.Таблицы.Найти("вт_Позиция").ПолучитьДанные().Выгрузить();

Особенности объединений и пакетных запросов

Рассмотрим ситуацию, когда в запросе используется ОБЪЕДИНИТЬ ВСЕ при помещении данных во временную таблицу. Проанализируем пример кода, который часто вызывает вопросы:


Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст = 
    "ВЫБРАТЬ 1 КАК Поле ПОМЕСТИТЬ ВТ
    |ОБЪЕДИНИТЬ ВСЕ
    |ВЫБРАТЬ 2
    |;
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ * ИЗ ВТ";

// После выполнения в ВТ будет 2 строки. 
// Но если вы смотрите результат в отладчике до выполнения второго запроса в пакете,
// вы можете увидеть некорректное состояние.
Результат = Запрос.Выполнить(); 

Помните, что ОБЪЕДИНИТЬ ВСЕ внутри конструкции ПОМЕСТИТЬ работает как единая операция. Все части объединения будут помещены в одну таблицу ВТ. Если же вы используете разные пакеты (разделенные точкой с запятой), то данные будут добавляться или перезаписываться в зависимости от текста запроса.

Оптимизация и производительность

Проанализируем дополнительные технические нюансы, которые помогут сделать работу с ВТ эффективнее:

Итоговый алгоритм действий при «пропаже» ВТ

Выясним последовательность действий, если вы не видите таблицу:

  1. Проверьте, инициализировано ли свойство Запрос.МенеджерВременныхТаблиц.
  2. Убедитесь, что запрос был выполнен (метод Выполнить() был вызван).
  3. В отладчике используйте Запрос.МенеджерВременныхТаблиц.Таблицы для проверки количества существующих ВТ.
  4. Для просмотра строк используйте ПолучитьДанные().Выгрузить() в окне вычисления выражений.
  5. Убедитесь, что параметры запроса (&Ссылка, &Сотрудник) установлены верно, иначе запрос ВЫБРАТЬ...ПОМЕСТИТЬ может просто не найти данных для помещения, и таблица останется физически существующей, но пустой.

Таким образом, правильное использование МенеджерВременныхТаблиц и методов ВыполнитьПакетСПромежуточнымиДанными() позволяет полностью контролировать процесс формирования данных и оперативно находить ошибки в сложной логике запросов.

← На главную