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