К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как создать менеджер временных таблиц в 1С

Пошаговая инструкция по созданию менеджера временных таблиц в 1С: код на встроенном языке, передача между запросами, типичные ошибки и проверка результата.

Менеджер временных таблиц в 1С — это объект встроенного языка, который хранит результаты запросов в виде именованных временных таблиц и позволяет использовать их в последующих запросах без повторного обращения к базе данных. Он незаменим, когда сложную выборку нужно разбить на этапы: сначала отобрать и сгруппировать данные, затем соединить промежуточный результат с другими таблицами.

Типичный сценарий — отчёт, где сначала формируется таблица остатков, потом она соединяется с оборотами, а затем с ценами. Без менеджера временных таблиц пришлось бы либо строить громоздкий запрос с множеством вложенных подзапросов, либо выгружать промежуточные данные в таблицы значений и передавать их параметрами. Оба варианта медленнее и труднее в сопровождении.

Ниже разобрано, как программно создать менеджер временных таблиц, помещать в него данные, передавать его между процедурами и проверять корректность работы. Все примеры ориентированы на управляемое приложение, но подходят и для обычных форм.

Что такое менеджер временных таблиц и когда он нужен

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

Физически временные таблицы размещаются в служебной базе tempdb СУБД (в клиент-серверном варианте) или во временном хранилище файловой базы. Они живут, пока жив менеджер: после уничтожения объекта или вызова метода Закрыть() все временные таблицы удаляются.

Использовать менеджер стоит, когда выполняется хотя бы одно из условий: запрос логически делится на этапы, промежуточный результат нужен нескольким запросам, или один и тот же отбор используется в пакете запросов. Для одиночного простого запроса менеджер избыточен.

Создание менеджера и привязка к запросу

Создание менеджера — одна строка кода. Далее его нужно присвоить свойству МенеджерВременныхТаблиц каждого запроса, который должен видеть общие временные таблицы. Если свойство не заполнить, запрос выполнится в собственном неявном менеджере, и чужие временные таблицы ему будут недоступны.

МенеджерВТ = Новый МенеджерВременныхТаблиц;

Запрос = Новый Запрос;

Запрос.МенеджерВременныхТаблиц = МенеджерВТ;

Запрос.Текст =

"ВЫБРАТЬ

| Продажи.Номенклатура КАК Номенклатура,

| СУММА(Продажи.Количество) КАК Количество

|ПОМЕСТИТЬ ВТ_Продажи

|ИЗ

| РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК Продажи

|СГРУППИРОВАТЬ ПО

| Продажи.Номенклатура";

Запрос.УстановитьПараметр("НачалоПериода", НачалоПериода);

Запрос.УстановитьПараметр("КонецПериода", КонецПериода);

Запрос.Выполнить();

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

Порядок создания менеджера временных таблиц
  1. 1
    Создайте объект: МенеджерВТ = Новый МенеджерВременныхТаблиц
  2. 2
    Создайте запрос и присвойте Запрос.МенеджерВременныхТаблиц = МенеджерВТ
  3. 3
    В тексте запроса используйте ПОМЕСТИТЬ ИмяТаблицы для сохранения промежуточных данных
  4. 4
    Выполните запрос методом Выполнить()
  5. 5
    Создайте следующий запрос с тем же менеджером и обратитесь к временной таблице по имени
  6. 6
    После завершения работы вызовите МенеджерВТ.Закрыть()

Помещение данных и работа с несколькими запросами

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

Запрос2 = Новый Запрос;

Запрос2.МенеджерВременныхТаблиц = МенеджерВТ;

Запрос2.Текст =

"ВЫБРАТЬ

| ВТ_Продажи.Номенклатура КАК Номенклатура,

| ВТ_Продажи.Количество КАК Количество,

| Цены.Цена КАК Цена

|ИЗ

| ВТ_Продажи КАК ВТ_Продажи

| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ) КАК Цены

| ПО ВТ_Продажи.Номенклатура = Цены.Номенклатура";

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

Один запрос может содержать пакет из нескольких операторов, разделённых точкой с запятой: первый помещает временную таблицу, второй читает её. Это удобно для компактного кода, но затрудняет отладку — при ошибке сложнее понять, на каком этапе она возникла. Для сложной логики предпочтительнее отдельные объекты запросов.

Временную таблицу можно удалить явно конструкцией УНИЧТОЖИТЬ ИмяТаблицы в тексте запроса. Это полезно, когда промежуточные данные больше не нужны, а менеджер продолжает использоваться: освобождается память и место в tempdb.

Передача менеджера между процедурами и внешними источниками

Менеджер временных таблиц — ссылочный объект, поэтому его можно передавать параметром в процедуры и функции общих модулей. Все вызванные процедуры будут работать с одним набором временных таблиц. Это стандартный способ организации многоэтапных расчётов: модуль верхнего уровня создаёт менеджер, а вспомогательные процедуры наполняют его.

Есть и обратная задача — передать во временную таблицу данные, полученные не запросом, а, например, таблицу значений. Для этого таблица значений передаётся параметром запроса, а в тексте используется выборка из параметра: ВЫБРАТЬ Т.Поле ПОМЕСТИТЬ ВТ_Данные ИЗ &ТаблицаЗначений КАК Т.

Передача большой таблицы значений параметром запроса — затратная операция: данные сериализуются и загружаются во временную таблицу СУБД. Если строк десятки тысяч и больше, сравните по времени с вариантом прямого запроса к регистру — часто обращение к базе оказывается быстрее.
ПЗ
Практическое замечание

Учтите ограничение: менеджер временных таблиц нельзя передать между клиентом и сервером и между сеансами. Он существует только в рамках одного серверного вызова (или клиентского контекста в толстом клиенте). Если данные нужны в другом сеансе, их придётся материализовать — выгрузить в таблицу значений и передать через временное хранилище.

Особенности в СКД и типовых механизмах

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

При программной инициализации СКД менеджер передаётся в процессор компоновки через объект внешних наборов данных или напрямую, если схема использует запрос с временными таблицами. Важно, чтобы менеджер был создан и заполнен до инициализации процессора компоновки — иначе СКД не найдёт нужные таблицы и выдаст ошибку.

Типичные ошибки и их последствия

Самая частая ошибка — обращение к временной таблице из запроса, у которого не заполнено свойство МенеджерВременныхТаблиц. Платформа сообщает, что таблица не найдена, хотя она была создана. Вторая по частоте — повторное помещение таблицы с тем же именем без предварительного УНИЧТОЖИТЬ.

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

Типичные ошибки
01
Запрос без привязки к менеджеру — ошибка «Таблица не найдена» при обращении к временной таблице
02
Повторное ПОМЕСТИТЬ с тем же именем — ошибка выполнения запроса; добавьте УНИЧТОЖИТЬ или проверку
03
Отсутствие ИНДЕКСИРОВАТЬ ПО на больших временных таблицах — медленные соединения
04
Утечка ресурсов: менеджер не закрывается, временные таблицы копятся в tempdb до конца сеанса
05
Отбор во временную таблицу без виртуальных таблиц и параметров — помещаются миллионы лишних строк

Проверка результата и отладка

Проверить содержимое временной таблицы можно простым запросом: ВЫБРАТЬ * ИЗ ВТ_Продажи с тем же менеджером. В отладчике удобно выгружать результат в таблицу значений и смотреть её через «Вычислить выражение». Так вы убедитесь, что на каждом этапе в таблице именно те строки, которые ожидались.

Для диагностики структуры менеджера используется метод Таблицы — коллекция описаний временных таблиц с именами и списками колонок. Это помогает программно проверить, существует ли нужная таблица, прежде чем обращаться к ней.

Контрольные точки

Как проверить результат

Свойство МенеджерВременныхТаблиц у всех запросов
Норма

Все запросы ссылаются на один объект менеджера

Тревожный признак

У части запросов свойство пустое — временные таблицы им недоступны

Содержимое временной таблицы
Норма

Запрос ВЫБРАТЬ * ИЗ ВТ_Имя возвращает ожидаемые строки

Тревожный признак

Пустой результат или лишние строки — ошибка в условиях помещающего запроса

Очистка ресурсов
Норма

После работы вызван МенеджерВТ.Закрыть() или применено УНИЧТОЖИТЬ

Тревожный признак

Менеджер живёт весь сеанс, tempdb растёт

Часто задаваемые вопросы

Чем менеджер временных таблиц отличается от таблицы значений?

Таблица значений — объект в памяти приложения, с ней работают циклами и методами встроенного языка. Временная таблица хранится на стороне СУБД и участвует в запросах: соединениях, группировках, отборах. Для обработки внутри запроса эффективнее временные таблицы, для построчной логики и передачи на клиента — таблицы значений.

Можно ли использовать один менеджер в нескольких потоках или фоновых заданиях?

Нет. Менеджер временных таблиц привязан к текущему сеансу и контексту исполнения. В фоновое задание его передать нельзя — там нужно создать собственный менеджер и заново поместить необходимые данные либо передать их через параметры и временное хранилище.

Что происходит с временными таблицами после закрытия менеджера?

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

Как узнать, существует ли временная таблица в менеджере?

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

Нужно ли индексировать временные таблицы всегда?

Нет. Индексация оправдана, когда временная таблица содержит заметное количество строк и участвует в соединениях или условиях по конкретным полям. Для маленьких таблиц из нескольких десятков строк создание индекса только добавляет накладные расходы без выигрыша в скорости.

Можно ли создать временную таблицу без менеджера?

Да, если выполнить запрос с ПОМЕСТИТЬ без заданного менеджера, платформа создаст неявный менеджер внутри этого объекта запроса. Но обратиться к такой таблице из другого запроса уже нельзя — поэтому для многоэтапной логики всегда создавайте менеджер явно.

Итог

Что важно запомнить

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