Разработка и Конфигурация · 12 мин
Как уничтожить временную таблицу в запросе 1С
Как уничтожить временную таблицу в запросе 1С: метод Уничтожить, конструкция УНИЧТОЖИТЬ, освобождение менеджера временных таблиц и типичные ошибки разработчика.
Временные таблицы в запросах 1С ускоряют выборку данных и упрощают сложную логику, но каждая такая таблица занимает память сервера до тех пор, пока жив менеджер временных таблиц. Если разработчик создаёт десятки таблиц в цикле и не удаляет их, объём потребляемой памяти растёт, а производительность запросов падает — сервер вынужден обслуживать всё более тяжёлый пакет.
Уничтожить временную таблицу можно двумя способами: непосредственно в тексте запроса конструкцией УНИЧТОЖИТЬ ИмяТаблицы либо из встроенного языка методом менеджера временных таблиц. Дополнительно вся цепочка таблиц автоматически удаляется, когда сам менеджер выходит из области видимости или явно закрывается методом Закрыть().
Ниже разобраны оба механизма, показаны рабочие примеры кода, типичные сценарии из реальных конфигураций и ошибки, из-за которых таблицы «повисают» в памяти или, наоборот, исчезают раньше времени.
Что такое временная таблица и где она хранится
Временная таблица — это именованный набор данных, созданный запросом с конструкцией ПОМЕСТИТЬ ИмяТаблицы и существующий внутри менеджера временных таблиц. Физически данные размещаются в памяти сервера 1С:Предприятия (или в памяти клиентского процесса при файловой базе), а не в базе данных, поэтому никакие записи в СУБД не сохраняются.
Ключевой момент: временная таблица живёт ровно столько, сколько живёт её менеджер. Если менеджер создан явно через Новый МенеджерВременныхТаблиц, таблица существует, пока переменная доступна и менеджер не закрыт. Если менеджер не задан, платформа создаёт неявный менеджер на время выполнения запроса — и все таблицы пакета удаляются автоматически после его завершения.
Из этого следуют два разных режима работы. В пакетном запросе без явного менеджера заботиться об удалении не нужно — всё очистится само. А вот при использовании явного менеджера, особенно в циклах и длительных процедурах, удаление таблиц становится обязанностью разработчика.
Уничтожение таблицы конструкцией УНИЧТОЖИТЬ в тексте запроса
Основной способ удаления — конструкция языка запросов УНИЧТОЖИТЬ, за которой следует имя таблицы. Она используется как отдельный оператор пакетного запроса, отделяется точкой с запятой и может применяться несколько раз в одном пакете.
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос.Текст =
"ВЫБРАТЬ
| Товары.Номенклатура,
| Товары.Количество
|ПОМЕСТИТЬ ВТ_Отбор
|ИЗ
| &Товары КАК Товары
|;
|
|ВЫБРАТЬ
| ВТ_Отбор.Номенклатура
|ИЗ
| ВТ_Отбор КАК ВТ_Отбор
|;
|
|УНИЧТОЖИТЬ ВТ_Отбор";
Запрос.Выполнить();
Порядок операторов в пакете имеет значение: УНИЧТОЖИТЬ должно стоять после последнего обращения к таблице. Если уничтожить таблицу раньше, чем её прочитает следующий подзапрос, запрос завершится ошибкой «Таблица не найдена». Платформа не отслеживает зависимости автоматически — ответственность за порядок лежит на разработчике.
Удалять промежуточные таблицы прямо в пакете стоит тогда, когда таблица нужна только для одного-двух шагов вычислений, а сам пакет длинный и создаёт много промежуточных данных. Это снижает пиковое потребление памяти без разбиения логики на отдельные запросы.
Удаление таблицы из кода через менеджер временных таблиц
Когда таблица создана одним запросом, а используется другими запросами с общим менеджером, уничтожить её можно отдельным коротким запросом, содержащим только оператор УНИЧТОЖИТЬ. Это стандартный приём в процедурах, где менеджер живёт долго и наполняется поэтапно.
ЗапросУдаления = Новый Запрос;
ЗапросУдаления.МенеджерВременныхТаблиц = МенеджерВТ;
ЗапросУдаления.Текст = "УНИЧТОЖИТЬ ВТ_ПромежуточныеДанные";
ЗапросУдаления.Выполнить();
Такой подход удобен в циклах: на каждой итерации создаётся таблица с одним и тем же именем, обрабатывается и сразу удаляется. Без удаления следующая попытка выполнить ПОМЕСТИТЬ с тем же именем вызовет ошибку — платформа не позволяет поместить таблицу поверх существующей с тем же именем.
Отдельный запрос на удаление также полезен, когда логика ветвится: в одной ветке таблица ещё нужна, в другой — уже нет. Условное уничтожение из кода даёт гибкость, которой нет у жёстко зашитого пакета.
- 1Создайте менеджер: МенеджерВТ = Новый МенеджерВременныхТаблиц
- 2В цикле выполняйте запрос с ПОМЕСТИТЬ ВТ_Данные и нужной обработкой
- 3После использования выполните запрос с текстом УНИЧТОЖИТЬ ВТ_Данные через тот же менеджер
- 4После выхода из цикла вызовите МенеджерВТ.Закрыть()
- 5Проверьте в отладчике, что повторный ПОМЕСТИТЬ не вызывает ошибки дублирования имени
Закрытие менеджера как способ удалить все таблицы сразу
Метод Закрыть() менеджера временных таблиц уничтожает все созданные в нём таблицы одним вызовом. Это правильная завершающая операция для любой процедуры, где менеджер создавался явно: даже если вы аккуратно удаляли таблицы по одной, закрытие гарантирует, что ничего не осталось.
МенеджерВТ = Новый МенеджерВременныхТаблиц;
// ... серия запросов с временными таблицами ...
МенеджерВТ.Закрыть();
После вызова Закрыть() повторное использование того же менеджера невозможно — обращение к нему приведёт к ошибке. Если таблицы нужны дальше, создавайте новый менеджер.
Альтернативный вариант — не закрывать менеджер вручную, а дать переменной выйти из области видимости. Платформа освободит ресурсы при сборке мусора, но момент освобождения не гарантирован. В длительных серверных процедурах и фоновых заданиях явное закрытие надёжнее: память возвращается сразу, а не «когда-нибудь».
Когда удалять таблицы обязательно, а когда не нужно
Обязательное удаление требуется в трёх ситуациях. Первая — циклы с повторным ПОМЕСТИТЬ под одним именем: без УНИЧТОЖИТЬ вторая итерация упадёт с ошибкой. Вторая — длительные фоновые задания и обработки больших объёмов, где десятки таблиц накапливаются и съедают память сервера. Третья — общий менеджер, передаваемый между процедурами: чем дольше он живёт, тем важнее подчищать ненужные таблицы.
Не требуется ручное удаление, когда весь запрос выполняется одним пакетом без явного менеджера. Платформа создаёт временный менеджер на время выполнения и удаляет всё автоматически. Добавлять УНИЧТОЖИТЬ в конец такого пакета можно, но практического эффекта это почти не даёт — разве что освобождает память чуть раньше внутри самого пакета.
Пограничный случай — отчёты на СКД и консоли запросов. Там временные таблицы обычно живут в рамках одного выполнения и удаляются платформой самостоятельно. Вмешательство нужно только если вы программно дополняете схему своими запросами с общим менеджером.
Как выбрать способ удаления
Типичные ошибки и как их избежать
Самая частая ошибка — обращение к таблице после её уничтожения. Она возникает при рефакторинге: разработчик добавляет УНИЧТОЖИТЬ в пакет, не заметив, что ниже по тексту есть ещё одно обращение к этой таблице. Защита проста: перед удалением выполните поиск имени таблицы по всему тексту запроса и по всем процедурам, работающим с общим менеджером.
Вторая ошибка — попытка повторного ПОМЕСТИТЬ под занятым именем. Если предыдущее удаление забытого запроса не выполнилось (например, код прервался исключением), следующий запуск упадёт. Надёжный паттерн — оборачивать работу с менеджером в попытку, а в блоке Исключение или после неё гарантированно закрывать менеджер.
Третья группа проблем — утечки памяти в фоновых заданиях. Симптомы характерные: задание работает всё медленнее, потребление памяти рабочего процесса растёт, в технологическом журнале видны длительные запросы. Лечится систематическим удалением промежуточных таблиц и закрытием менеджера в конце каждой порции обработки, а не только в конце всего задания.
Проверка результата и отладка
Убедиться, что таблица уничтожена, можно в отладчике: после выполнения УНИЧТОЖИТЬ попытка выполнить запрос ВЫБРАТЬ * ИЗ ИмяТаблицы через тот же менеджер должна завершиться ошибкой о ненайденной таблице. Отсутствие ошибки означает, что удаление не сработало — например, запрос выполнялся с другим менеджером.
Проверьте, что все запросы цепочки используют один и тот же объект менеджера. Типичный промах — в одной процедуре менеджер передан параметром, а в другой создан заново; тогда УНИЧТОЖИТЬ во второй процедуре либо падает, либо удаляет «не ту» таблицу.
Для контроля памяти в массовых обработках полезно логировать количество итераций и точки удаления таблиц. Если после внедрения УНИЧТОЖИТЬ и Закрыть() скорость обработки стабилизировалась и перестала деградировать с ростом объёма данных — очистка работает правильно.
Как проверить результат
Ошибка «Таблица не найдена» при обращении к удалённой таблице
Запрос выполняется — удаление не сработало или использован другой менеджер
Каждая итерация выполняется без ошибок
Ошибка дублирования имени таблицы на второй итерации
Потребление стабильно на всех порциях данных
Память растёт с каждой итерацией — таблицы накапливаются
Что важно запомнить
Временную таблицу удаляют конструкцией УНИЧТОЖИТЬ в пакете или отдельным запросом, а весь набор таблиц — методом Закрыть() менеджера. Удаляйте таблицу только после последнего обращения к ней и всегда закрывайте явно созданный менеджер в конце работы.
Частые вопросы
Можно ли уничтожить временную таблицу, не зная менеджера?
Нет. Оператор УНИЧТОЖИТЬ выполняется запросом, а запрос ищет таблицу в своём менеджере временных таблиц. Если менеджер не задан, используется неявный менеджер этого конкретного запроса — чужие таблицы он не увидит. Поэтому удалять таблицу нужно через тот же объект менеджера, в котором она создана.
Что будет, если не удалять временные таблицы вообще?
В разовом пакетном запросе — ничего страшного: платформа очистит всё автоматически после выполнения. В циклах и длительных процедурах с явным менеджером таблицы будут накапливаться, потребление памяти вырастет, а повторное использование имён приведёт к ошибкам. В фоновых заданиях это заметно деградирует производительность.
Можно ли уничтожить таблицу внутри того же запроса, который её создал?
Да, пакетный запрос позволяет: сначала ПОМЕСТИТЬ, затем один или несколько запросов, использующих таблицу, и в конце УНИЧТОЖИТЬ. Главное — чтобы оператор удаления стоял после последнего чтения таблицы, иначе запрос завершится ошибкой.
Удаляются ли временные таблицы при откате транзакции?
Нет. Временные таблицы не являются данными базы и не участвуют в транзакционной логике СУБД. Откат транзакции не удаляет и не восстанавливает временные таблицы — ими продолжает управлять менеджер. Если процедура прервана исключением, закрывайте менеджер в блоке обработки исключения.
Как удалить сразу несколько временных таблиц?
Либо перечислите несколько операторов УНИЧТОЖИТЬ в одном пакетном запросе через точку с запятой, либо вызовите Закрыть() у менеджера — тогда удалятся все таблицы разом. Второй вариант подходит, когда менеджер дальше не нужен; если часть таблиц ещё используется, удаляйте выборочно отдельными операторами.
Почему после УНИЧТОЖИТЬ запрос всё равно видит таблицу?
Чаще всего причина в том, что удаление и проверка выполняются через разные менеджеры временных таблиц: запрос с УНИЧТОЖИТЬ отработал в одном менеджере, а проверочный запрос создал свой неявный менеджер и нашёл таблицу, созданную ранее в другом месте. Проверьте, что свойство МенеджерВременныхТаблиц у всех запросов цепочки указывает на один и тот же объект.