SQL Server 中的本地临时表和全局临时表有什么区别?
7 回答
表变量(
DECLARE @t TABLE
) 仅对创建它的连接可见,并在批处理或存储过程结束时被删除。本地临时表(
CREATE TABLE #t
) 仅对创建它的连接可见,并在连接关闭时被删除。全局临时表(
CREATE TABLE ##t
) 对所有人可见,并在所有引用它们的连接都关闭时被删除。Tempdb 永久表(
USE tempdb CREATE TABLE t
) 对所有人可见,并在服务器重新启动时被删除。
我觉得这个解释很清楚(它是来自Technet的纯副本):
有两种类型的临时表:本地和全局。本地临时表仅在与 SQL Server 实例首次创建或引用表时相同的连接期间对其创建者可见。用户断开与 SQL Server 实例的连接后,本地临时表将被删除。全局临时表在创建后对任何用户和任何连接都是可见的,并在引用该表的所有用户与 SQL Server 实例断开连接时被删除。
1.) 本地临时表仅在连接期间存在,或者,如果在复合语句中定义,则在复合语句期间存在。
本地临时表仅对创建表的 SQL Server 会话或连接(即单个用户)可用。当创建表的会话关闭时,这些会自动删除。本地临时表名以单井号(“#”)开头。
CREATE TABLE #LocalTemp
(
UserID int,
Name varchar(50),
Address varchar(150)
)
GO
insert into #LocalTemp values ( 1, 'Name','Address');
GO
Select * from #LocalTemp
本地临时表的范围存在于当前用户的当前会话意味着当前查询窗口。如果您将关闭当前查询窗口或打开一个新的查询窗口并尝试查找上面创建的临时表,它将给您错误。
2.) 全局临时表永久保留在数据库中,但行仅存在于给定连接中。当连接关闭时,全局临时表中的数据消失。但是,下次打开数据库时,表定义仍保留在数据库中以供访问。
全局临时表可用于所有 SQL Server 会话或连接(意味着所有用户)。这些可以由任何 SQL Server 连接用户创建,并在所有 SQL Server 连接关闭后自动删除。全局临时表名用双井号(“##”)标记。
CREATE TABLE ##GlobalTemp
(
UserID int,
Name varchar(50),
Address varchar(150)
)
GO
insert into ##GlobalTemp values ( 1, 'Name','Address');
GO
Select * from ##GlobalTemp
全局临时表对所有 SQL Server 连接可见,而本地临时表仅对当前 SQL Server 连接可见。
引用在线书籍:
本地临时表只在当前会话中可见;全局临时表对所有会话可见。
临时表超出范围时会自动删除,除非使用 DROP TABLE 显式删除:
- 当存储过程完成时,会自动删除在存储过程中创建的本地临时表。该表可以被创建该表的存储过程执行的任何嵌套存储过程引用。调用创建该表的存储过程的进程无法引用该表。
- 所有其他本地临时表在当前会话结束时自动删除。
- 当创建表的会话结束并且所有其他任务停止引用它们时,将自动删除全局临时表。任务和表之间的关联仅在单个 Transact-SQL 语句的生命周期内维护。这意味着在创建会话结束时主动引用该表的最后一个 Transact-SQL 语句完成时将删除全局临时表。
我没有看到任何向用户显示我们可以在哪里找到全局临时表的答案。在 SSMS 中导航时,您可以在同一位置查看本地和全局临时表。以下截图取自此链接。
数据库 --> 系统数据库 --> tempdb --> 临时表
值得一提的是,还有:数据库作用域的全局临时表(目前只有 Azure SQL 数据库支持)。
SQL Server 的全局临时表(以## 表名启动)存储在 tempdb 中,并在整个 SQL Server 实例中的所有用户会话之间共享。
Azure SQL 数据库支持也存储在 tempdb 中并限定为数据库级别的全局临时表。这意味着全局临时表是为同一 Azure SQL 数据库中的所有用户会话共享的。来自其他数据库的用户会话无法访问全局临时表。
-- Session A creates a global temp table ##test in Azure SQL Database testdb1 -- and adds 1 row CREATE TABLE ##test ( a int, b int); INSERT INTO ##test values (1,1); -- Session B connects to Azure SQL Database testdb1 -- and can access table ##test created by session A SELECT * FROM ##test ---Results 1,1 -- Session C connects to another database in Azure SQL Database testdb2 -- and wants to access ##test created in testdb1. -- This select fails due to the database scope for the global temp tables SELECT * FROM ##test ---Results Msg 208, Level 16, State 0, Line 1 Invalid object name '##test'
GLOBAL_TEMPORARY_TABLE_AUTODROP = { ON | OFF }
适用于:Azure SQL 数据库(功能为公共预览版)
允许为全局临时表设置自动删除功能。默认值为 ON,这意味着全局临时表在不被任何会话使用时会自动删除。设置为 OFF 时,需要使用 DROP TABLE 语句显式删除全局临时表,否则将在服务器重新启动时自动删除。
使用 Azure SQL 数据库单一数据库和弹性池,可以在 SQL 数据库服务器的单个用户数据库中设置此选项。在 SQL Server 和 Azure SQL 数据库托管实例中,此选项在 TempDB 中设置,单个用户数据库的设置无效。
本地临时表:如果您创建本地临时表,然后打开另一个连接并尝试查询,您将收到以下错误。
临时表只能在创建它们的会话中访问。
全局临时表:有时,您可能希望创建一个可访问其他连接的临时表。在这种情况下,您可以使用全局临时表。
全局临时表只有在所有引用它的会话都关闭时才会被销毁。