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

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

Временные таблицы в 1С 8.3: что это и зачем они нужны

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

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

Механизм временных таблиц доступен во встроенном языке запросов платформы 1С:Предприятие 8.3 и управляется через объект МенеджерВременныхТаблиц. Разработчики применяют его при построении отчётов, сложных выборках остатков, дозаполнении документов и оптимизации обращений к базе. Без временных таблиц многие задачи пришлось бы решать громоздкими вложенными запросами или многократными обращениями к одним и тем же данным.

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

Как устроен механизм временных таблиц

Когда запрос содержит конструкцию ПОМЕСТИТЬ ИмяТаблицы, платформа выполняет выборку и сохраняет результат во временное хранилище. Физически данные размещаются в памяти сервера 1С или в временной таблице на стороне СУБД — это зависит от режима работы и версии платформы. Разработчику детали хранения не важны: доступ к данным идёт только через запросы того же менеджера временных таблиц.

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

После закрытия менеджера (метод Закрыть()) или его уничтожения все временные таблицы удаляются. Пока менеджер существует, таблицы занимают память, поэтому при работе с большими выборками важно не забывать освобождать ресурсы.

Создание временной таблицы: конструкция ПОМЕСТИТЬ

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

ВЫБРАТЬ

Товары.Ссылка КАК Номенклатура,

Товары.Цена КАК Цена

ПОМЕСТИТЬ ВТ_Товары

ИЗ

Справочник.Номенклатура КАК Товары

ГДЕ

Товары.Цена > 0

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

Можно создать временную таблицу и из внешнего источника — таблицы значений, сформированной в коде. Для этого используется параметр запроса с типом «ТаблицаЗначений» и выборка ИЗ &Таблица КАК Таблица. Так приём применяют, когда нужно соединить данные базы с данными, рассчитанными программно.

bsl
МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос.Текст = "ВЫБРАТЬ Товары.Ссылка КАК Номенклатура
|ПОМЕСТИТЬ ВТ_Товары
|ИЗ Справочник.Номенклатура КАК Товары
|ГДЕ Товары.Цена > 0";
Запрос.Выполнить();

Использование временных таблиц в последующих запросах

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

ВЫБРАТЬ

ВТ.Номенклатура КАК Номенклатура,

СУММА(Остатки.КоличествоОстаток) КАК Остаток

ИЗ

ВТ_Товары КАК ВТ

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки

ПО ВТ.Номенклатура = Остатки.Номенклатура

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

ВТ.Номенклатура

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

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

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

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

Любую временную таблицу теоретически можно заменить вложенным запросом — результат будет тем же. Разница в удобстве сопровождения и в том, как платформа выполняет код. Вложенный запрос на три-четыре уровня вложенности тяжело читать и отлаживать: нельзя быстро посмотреть промежуточные данные. Временная таблица решает эту проблему — каждый этап доступен для проверки отдельно.

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

КритерийВременная таблицаВложенный запрос
Читаемость сложной логикиВысокая, этапы разделеныСнижается с ростом вложенности
Отладка промежуточных данныхМожно выгрузить и посмотретьТолько вручную выделяя подзапрос
Повторное использование результатаВычисляется один разМожет вычисляться повторно
Расход памяти сервераДанные хранятся в менеджереМинимальный
Простые одношаговые выборкиИзбыточныПредпочтительны

Когда что выбрать

Временная таблица

Подходит для многоэтапных запросов, повторного использования промежуточных данных и случаев, где нужна отладка. Ограничение — расход памяти на больших выборках.

Вложенный запрос

Подходит для простых одношаговых выборок без повторного использования. Ограничение — плохо читается при глубокой вложенности.

Пакетный запрос с несколькими ВТ

Подходит для отчётов и сложных обработок. Ограничение — требует аккуратного управления менеджером и своевременного УНИЧТОЖИТЬ.

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

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

ВЫБРАТЬ

Товары.Ссылка КАК Номенклатура

ПОМЕСТИТЬ ВТ_Товары

ИЗ

Справочник.Номенклатура КАК Товары

ИНДЕКСИРОВАТЬ ПО

Номенклатура

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

Ещё один фактор скорости — состав выбираемых полей. Не стоит помещать во временную таблицу все поля источника «про запас»: чем шире строка, тем больше памяти занимает таблица и тем медленнее идёт соединение. Выбирайте только те поля, которые понадобятся дальше.

Отладка и проверка содержимого

Главное преимущество временных таблиц — прозрачность промежуточных данных. Чтобы посмотреть, что попало в таблицу, достаточно в отладчике выполнить простой запрос ВЫБРАТЬ * ИЗ ВТ_Товары через тот же менеджер и выгрузить результат в таблицу значений. Это позволяет локализовать ошибку: сразу видно, на каком этапе данные потерялись или продублировались.

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

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

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

Количество строк во временной таблице
Норма

Совпадает с ожидаемым числом отобранных записей

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

Ноль строк или в разы больше, чем в источнике

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

Каждая строка ВТ дала не более одной строки результата

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

Дублирование строк после ЛЕВОЕ СОЕДИНЕНИЕ

Память после выполнения обработки
Норма

Менеджер закрыт, таблицы уничтожены

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

МенеджерВТ.Закрыть() не вызывается, память растёт

Типичные ошибки и ограничения

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

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

Ограничения механизма: временные таблицы нельзя использовать в запросах к другим информационным базам, они не передаются между клиентом и сервером и недоступны после закрытия менеджера. Также нельзя поместить во временную таблицу поля неограниченной длины без приведения типов — используйте ВЫРАЗИТЬ для строк и хранимых данных.

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

Практические сценарии применения

В отчётах на СКД временные таблицы применяют через набор данных «Запрос» с пакетным текстом: сначала готовятся вспомогательные выборки, затем финальный запрос собирает результат. Это стандартный приём для отчётов с несколькими уровнями агрегации.

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

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

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

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

Где физически хранится временная таблица в 1С?

В оперативной памяти сервера 1С:Предприятия, а в клиент-серверном режиме часть операций может выполняться средствами СУБД. В базу данных временная таблица не записывается и после завершения менеджера временных таблиц удаляется без следа.

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

Да, но только если этот запрос использует тот же объект МенеджерВременныхТаблиц. Присвойте свойству МенеджерВременныхТаблиц второго запроса тот же экземпляр, и таблица станет доступна по имени.

Чем удалить временную таблицу до конца пакета?

Конструкцией УНИЧТОЖИТЬ ИмяТаблицы в тексте запроса. Это освобождает память сразу, не дожидаясь закрытия менеджера, и полезно в длинных пакетах с несколькими промежуточными этапами.

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

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

Почему возникает ошибка «Таблица не найдена»?

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

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

Да. Установите параметр запроса со значением типа ТаблицаЗначений, затем выполните выборку ИЗ &ИмяПараметра с конструкцией ПОМЕСТИТЬ. Колонки таблицы значений станут полями временной таблицы.

Итог

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

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