Эти занимательные временные таблицы
Кое-что интересное о временных таблицах и работе платформы 1С с ними.
- Описание
- Подробнее
Описание
Мы все их используем
Не важно — новичок Вы или опытный разработчик. Если когда-либо в работе приходилось создавать запросы, то с высокой долей вероятности в них хотя бы раз были использованы временные таблицы. Тот же экзамен "1С:Специалист по платформе" фактически требует их использования при решении задач на экзамене. Сегодня речь будет идти, внезапно, как-раз о временных таблицах и работе платформы 1С с ними.
Мы начнем с простых примеров работы с временными таблицами и действиями платформы на стороне СУБД. А закончим чем-то очень странным и неожиданным.
Для всех примеров и экспериментов использовалась платформа 1С:Предприятие 8.3.16.1063 в клиент-серверном режиме работы. В качестве СУБД выступал SQL Server 2017. Для изучения действий платформы использовались следующие инструменты:
- Транслятор запросов 1С в SQL для удобного отлавливания запросов платформы 1С на стороне СУБД, но можно использовать и просто Extended Events.
- Просмотр и анализ структуры базы данных (отчет на СКД) — для удобного просмотра структуры таблиц объектов в базе данных.
- Azure Data Studio для просмотра соединений и других действия на стороне SQL Server. Для этих целей можно также использовать старый добрый SQL Server Management Studio.
- Конфигурацию "Бухгалтерия предприятия 3".
- Желание "поковырять" платформу как мотивацию 🙂
Интересно? Добро пожаловать!
Примитивный пример
Временные таблицы рекомендуется использовать для создания стабильных и производительных запросов. В тексте запросов их создание выполняется с помощью ключевого слова "ПОМЕСТИТЬ" для пакета запроса.
ВЫБРАТЬ ПЕРВЫЕ 100
Номенклатура.Ссылка КАК Ссылка,
Номенклатура.Наименование КАК Наименование
ПОМЕСТИТЬ ВТ_Номенклатура
ИЗ
Справочник.Номенклатура КАК Номенклатура
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_Номенклатура.Ссылка КАК Ссылка,
ВТ_Номенклатура.Наименование КАК Наименование
ИЗ
ВТ_Номенклатура КАК ВТ_Номенклатура
Здесь в первом пакете запросов мы выбрали первые 100 элементов справочника "Номенклатура" и поместили их во временную таблицу "ВТ_Номенклатура". После чего во втором пакете мы получили данные из ранее созданной временной таблицы и вернули их как результат выборки. Все просто, не так ли?
Если взглянуть на происходящее на стороне СУБД, то мы увидим следующую серию запросов.
-- Проверка существует ли временная таблица с указанным именем
SELECT
1
WHERE OBJECT_ID('tempdb..#tt36') IS NOT NULL
-- Создание временной таблицы с зарезервированным именем и необходимой структурой
CREATE TABLE #tt36 (
_Q_000_F_000RRef BINARY(16),
_Q_000_F_001 NVARCHAR(100) COLLATE DATABASE_DEFAULT
)
-- Выполнение 1 пакета запроса для заполнения временной таблицы
INSERT INTO #tt36 WITH(TABLOCK) (_Q_000_F_000RRef, _Q_000_F_001) SELECT TOP 100
T1._IDRRef,
T1._Description
FROM dbo._Reference85 T1
WHERE (T1._Fld774 = @P1) -- Неявный отбор по разделителю данных
-- Получение данных из временной таблицы для результата запроса
SELECT
T1._Q_000_F_000RRef,
T1._Q_000_F_001
FROM #tt36 T1 WITH(NOLOCK)
-- Очистка временной таблицы
TRUNCATE TABLE #tt36
Тоже все относительно просто. Платформа 1С выполняет ряд простых шагов:
- Проверка наличия временной таблицы с зарезервированным именем. Если существует, то будет удалена.
- Создание временной таблицы.
- Далее выполняет запрос из первого пакета для наполнения данных ранее созданной временной таблицы.
- Вторым запросом получает данные из временной таблицы для результата выборки.
- Очищает данные временной таблицы.
В нашем случае последней операцией является очистка временной таблицы, причем платформа делает это автоматически. Так происходит, потому что запрос был окончательно выполнен и за ним можно освободить ресурсы. Очистку данных временной таблицы также можно добавить явно указав инструкции в запросе:
;
////////////////////////////////////////////////////////////////////////////////
УНИЧТОЖИТЬ ВТ_Номенклатура
Всегда ли платформа действует по таким правилам? Нет. Например, если выполнить этот же запрос еще раз, то количество выполняемых SQL-запросов будет меньше.
-- Выполнение 1 пакета запроса для заполнения временной таблицы
INSERT INTO #tt36 WITH(TABLOCK) (_Q_000_F_000RRef, _Q_000_F_001) SELECT TOP 100
T1._IDRRef,
T1._Description
FROM dbo._Reference85 T1
WHERE (T1._Fld774 = @P1) -- Неявный отбор по разделителю данных
-- Получение данных из временной таблицы для результата запроса
SELECT
T1._Q_000_F_000RRef,
T1._Q_000_F_001
FROM #tt36 T1 WITH(NOLOCK)
-- Очистка временной таблицы
TRUNCATE TABLE #tt36
Платформа увидела, что пустая временная таблица с необходимой структурой уже есть на стороне базы данных для текущего соединения с СУБД и не стала создавать ее заново. Эта оптимизация позволяет работать с временными таблицами наиболее эффективно, не создавая каждый раз их заново.
Также обратите внимание на проверку существования временной таблицы выше. Ранее редко, но метко, можно было нарваться на ошибку уже существующей временной таблицы с именем "#ttN’. Помню такое еще со времен 8.3.6. Теперь это более редкая проблема и это поведение одна из причин изменения ситуации.
Итак, создание временных таблиц выполняется довольно просто. Это относится как в части использования конструкции "ПОМЕСТИТЬ" в запросе, так и в части SQL-запросов платформы 1С. Даже переиспользование ранее созданных временных таблиц не усложняет пример. Но все ли так просто на самом деле?
Серийное производство
Усложним пример и создадим намного больше временных таблиц в запросе. Вот как это выглядит в контексте 1С.