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

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

Временная таблица в 1С: что это и как с ней работать

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

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

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

Работа с временными таблицами доступна в любой конфигурации на платформе 1С:Предприятие 8 — через конструктор запроса или напрямую в коде. Ниже разберём синтаксис, менеджер временных таблиц, практические сценарии и ограничения механизма.

Что такое временная таблица и чем она отличается от обычной

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

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

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

Как создать временную таблицу: оператор ПОМЕСТИТЬ

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

ВЫБРАТЬ

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

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

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

ИЗ

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

ГДЕ

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

;

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

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

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

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

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

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

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

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

Передача таблицы значений во временную таблицу

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

ВЫБРАТЬ

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

ТЗ.Количество КАК Количество

ПОМЕСТИТЬ ВТ_Данные

ИЗ

&ТЗ КАК ТЗ

;

В коде параметр устанавливается так: Запрос.УстановитьПараметр("ТЗ", ТаблицаЗначений). Имена колонок в тексте запроса должны совпадать с именами колонок таблицы значений. Далее ВТ_Данные соединяется с регистрами или справочниками — и вся обработка идёт на стороне СУБД без циклов.

Это правильная замена антипаттерну «перебор в цикле с запросом внутри». Запрос в цикле выполняет обращение к базе на каждую итерацию, а один пакетный запрос с временной таблицей — одно обращение на весь объём данных.

Сравнение вариантов

Пакетный запрос с временными таблицами

Подходит для сложных многоэтапных выборок; вся логика на стороне СУБД, быстро на больших объёмах. Ограничение — сложнее отлаживать промежуточные шаги.

Таблица значений + обход в коде

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

Вложенные подзапросы без ПОМЕСТИТЬ

Подходят для простых случаев из 1–2 уровней вложенности. При глубокой вложенности текст становится нечитаемым, а СУБД может строить менее эффективный план.

Удаление временных таблиц и управление памятью

Временные таблицы потребляют память — на сервере 1С или в tempdb СУБД. Если пакетный запрос создаёт несколько крупных таблиц, а дальше используются не все, лишние стоит удалять явно оператором УНИЧТОЖИТЬ ВТ_Имя. Это отдельный запрос в пакете, состоящий из одной инструкции.

Если используется явный менеджер временных таблиц, все его таблицы живут, пока жив сам менеджер. В длительных серверных процедурах с несколькими этапами обработки это может привести к заметному росту потребления памяти. Признак проблемы — замедление выполнения последующих запросов и рост tempdb на SQL Server.

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

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

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

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

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

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

Как проверить результат и отладить пакетный запрос

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

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

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

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

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

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

Строки соответствуют условиям отбора, нет дублей сверх ожидаемых

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

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

Время выполнения пакета
Норма

Запрос выполняется за секунды на рабочем объёме данных

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

Выполнение занимает минуты, tempdb на SQL Server заметно растёт

Итоговое соединение с ВТ
Норма

Соединение возвращает ожидаемое число строк без размножения

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

Строки дублируются — вероятно, соединение по неуникальному полю

Частые вопросы о временных таблицах в 1С

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

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

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

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

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

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

Зачем нужно ИНДЕКСИРОВАТЬ ПО во временной таблице?

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

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

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

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

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

Итог

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

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