临时表
可以创建本地临时表和全局临时表。 本地临时表仅在当前会话中可见,而全局临时表在所有会话中都可见。 临时表不能分区。
本地临时表的名称前面有一个数字符号 (#table_name),而全局临时表的名称前面有两个数字符号 (##table_name)。
SQL 语句使用 CREATE TABLE 语句中为 table_name 指定的值引用临时表,例如:
复制
CREATE TABLE #MyTempTable (cola INT PRIMARY KEY);
INSERT INTO #MyTempTable VALUES (1);
如果在单个存储过程或批处理中创建了多个临时表,则它们必须有不同的名称。
如果本地临时表由存储过程创建或由多个用户同时执行的应用程序创建,则数据库引擎必须能够区分由不同用户创建的表。 为此,数据库引擎在内部为每个本地临时表的表名追加一个数字后缀。 存储在 tempdb 的 sysobjects 表中的临时表,其全名由 CREATE TABLE 语句中指定的表名和系统生成的数字后缀组成。 为了允许追加后缀,为本地临时表指定的 table_name 不能超过 116 个字符。
除非使用 DROP TABLE 显式删除临时表,否则临时表将在退出其作用域时由系统自动删除:
- 当存储过程完成时,将自动删除在存储过程中创建的本地临时表。 由创建表的存储过程执行的所有嵌套存储过程都可以引用此表。 但调用创建此表的存储过程的进程无法引用此表。
- 所有其他本地临时表在当前会话结束时都将被自动删除。
- 全局临时表在创建此表的会话结束且其他所有任务停止对其引用时将被自动删除。 任务与表之间的关联只在单个 Transact-SQL 语句的生存周期内保持。 换言之,当创建全局临时表的会话结束时,最后一条引用此表的 Transact-SQL 语句完成后,将自动删除此表。
在存储过程或触发器中创建的本地临时表的名称可以与在调用存储过程或触发器之前创建的临时表名称相同。 但是,如果查询引用临时表,而同时有两个同名的临时表,则不定义针对哪个表解析该查询。 嵌套存储过程同样可以创建与调用它的存储过程所创建的临时表同名的临时表。 但是,为了对其进行修改以解析为在嵌套过程中创建的表,此表必须与调用过程创建的表具有相同的结构和列名。 下面的示例说明了这一点。
复制
CREATE PROCEDURE dbo.Test2
AS
CREATE TABLE #t(x INT PRIMARY KEY);
INSERT INTO #t VALUES (2);
SELECT Test2Col = x FROM #t;
GO
CREATE PROCEDURE dbo.Test1
AS
CREATE TABLE #t(x INT PRIMARY KEY);
INSERT INTO #t VALUES (1);
SELECT Test1Col = x FROM #t;
EXEC Test2;
GO
CREATE TABLE #t(x INT PRIMARY KEY);
INSERT INTO #t VALUES (99);
GO
EXEC Test1;
GO
下面是结果集:
(1 row(s) affected)
Test1Col
-----------
1
(1 row(s) affected)
Test2Col
-----------
2
当创建本地或全局临时表时,CREATE TABLE 语法支持除 FOREIGN KEY 约束以外的其他所有约束定义。 如果临时表中指定了 FOREIGN KEY 约束,则该语句将返回一条表明已跳过此约束的警告消息。 此表仍将创建,但不使用 FOREIGN KEY 约束。 在 FOREIGN KEY 约束中不能引用临时表。
如果某个临时表是使用命名约束创建的,并且该临时表是在用户定义的事务的作用域内创建的,则一次只能有一个用户执行创建该临时表的语句。 例如,如果某一存储过程使用命名主键约束创建一个临时表,则多个用户无法同时执行该存储过程。
来自 <CREATE TABLE (Transact-SQL) | Microsoft Learn>
引申:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | IF EXISTS(SELECT 1 FROM sys.objects WHERE object_id= OBJECT_ID(N'dbo.PRC_SUB_TEST' ) AND OBJECTPROPERTY(object_id, 'IsProcedure')=1) BEGIN DROP PROCEDURE dbo.PRC_SUB_TEST; END GO CREATE PROCEDURE dbo.PRC_SUB_TEST AS BEGIN
SELECT * FROM #tmp_test; CREATE TABLE #tmp_test(name VARCHAR(128));
INSERT INTO #tmp_test SELECT name FROM sys.objects
SELECT * FROM #tmp_test; END GO |
通过实验验证,我们发现外层存储过程的临时表在内层存储过程中有效,它的“作用域”是在内层存储过程的同名临时表创建之前,这个跟高级语言中的全局变量和局部变量作用域有点类似

603






