В практике разработчика 1С иногда возникают ситуации, которые кажутся магическими или нарушающими логику работы платформы. Одна из таких проблем — внезапное появление временной таблицы в Менеджере временных таблиц еще до того, как в программном коде был вызван метод Выполнить(). Это приводит к досадной ошибке «Временная таблица уже существует», которая блокирует дальнейшую работу алгоритма. В этой статье мы подробно разберем, почему это происходит, как на это влияет отладчик и какие практики помогут избежать подобных конфликтов.
Рассмотрим ситуацию: мы пишем сложный пакетный запрос, используем МенеджерВременныхТаблиц, и на определенном этапе платформа сообщает нам, что таблица с таким именем уже создана. Проверяя состояние объекта в отладчике, мы замечаем странную вещь: как только тексту запроса присваивается значение, таблица уже числится в менеджере, хотя команда на выполнение еще не поступала.
Основная причина кроется в механизме вычисления выражений в отладчике. Проанализируем, что происходит, когда мы используем окно «Табло» или «Вычислить выражение» (Shift+F9):
Запрос.Выполнить().Выгрузить(), платформа будет пытаться вычислить это значение на каждом шаге отладки (F10 или F11).Запрос для отображения его состояния, он может инициировать обращения к связанному с ним МенеджеруВременныхТаблиц.Выясним причину ошибки в вашем случае: если вы видите таблицу в менеджере сразу после присвоения текста, первым делом очистите список выражений в Табло и закройте все окна вычисления выражений. В большинстве случаев проблема исчезает после перезапуска сеанса отладки без активных «наблюдаемых» выражений.
Посмотрим на пример правильного управления ресурсами. МенеджерВременныхТаблиц — это объект, который хранит временные таблицы в течение всего времени своей жизни. Если вы используете один и тот же экземпляр менеджера для разных объектов Запрос, таблицы будут накапливаться.
Разберем по шагам, как предотвратить конфликты имен:
1. Явное уничтожение таблиц. Если временная таблица вам больше не нужна, всегда используйте инструкцию УНИЧТОЖИТЬ в тексте запроса. Это гарантирует, что при повторном проходе по коду или при использовании того же менеджера в другом месте, имя будет свободно.
ТекстЗапроса = "ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура ПОМЕСТИТЬ ВТ_Данные;
|...;
|УНИЧТОЖИТЬ ВТ_Данные";
Запрос.Текст = ТекстЗапроса;
Запрос.Выполнить();
2. Проверка существования таблицы. Перед тем как создавать таблицу, мы можем программно проверить, нет ли её в менеджере. Рассмотрим пример кода:
Если МенеджерВТ.Таблицы.Найти("ВТ_Данные") <> Неопределено Тогда
// Таблица уже есть, можно либо уничтожить её отдельным запросом,
// либо использовать существующую
КонецЕсли;
Проанализируем ситуацию, когда запросов много и они выполняются в цикле. Очистка ссылки на менеджер (присвоение Неопределено) не всегда моментально удаляет таблицы из СУБД (например, в tempdb на MS SQL Server). Для надежного освобождения ресурсов рекомендуется использовать метод Закрыть().
Рассмотрим пример правильной инициализации в цикле:
Для Каждого СтрокаПараметров Из СписокПараметров Цикл
МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
// ... выполнение запроса ...
// Обязательно закрываем менеджер в конце итерации
МенеджерВТ.Закрыть();
КонецЦикла;
Использование МенеджерВТ.Закрыть() принудительно удаляет все временные таблицы, связанные с этим объектом, и разрывает связь с сеансом в СУБД. Это самый надежный способ избежать ошибки «Временная таблица уже существует» при многократном выполнении кода.
Иногда проблема может быть вызвана некорректным состоянием кэша метаданных. Если после очистки «Табло» отладчика ошибка сохраняется, следует выполнить следующие действия:
%AppData%\1C\1cv8.Мы выяснили, что ошибка «Временная таблица уже существует» чаще всего является побочным эффектом отладки. Платформа, пытаясь «помочь» разработчику и показать содержимое переменных в режиме реального времени, выполняет запрос неявно.
Чтобы ваша разработка была стабильной, придерживайтесь трех золотых правил:
Выполнить() в окне «Табло».УНИЧТОЖИТЬ для временных таблиц, завершивших свой жизненный цикл.Закрыть() для объектов МенеджерВременныхТаблиц, когда работа с ними завершена, особенно внутри циклов или длительных процедур.Соблюдение этих рекомендаций позволит вам избежать труднодиагностируемых ошибок и сделает ваш код более профессиональным и отказоустойчивым.