2016-05-31 104 views
3

SQL Server支持临时表(本地和全局)。临时存储过程范围

使用动态SQL(EXECdbo.sp_executesql),我们可以创建新的上下文,并且本地临时表只在动态SQL块中可见,但不在外部。

-- Normal table 
EXEC ('CREATE TABLE tab(i INT); INSERT INTO tab(i) VALUES (1)'); 
SELECT * FROM tab; 

-- Global temporary table 
EXEC ('CREATE TABLE ##tab(i INT); INSERT INTO ##tab(i) VALUES (2)'); 
SELECT * FROM ##tab; 

-- Local temporary table 
EXEC ('CREATE TABLE #tab(i INT); INSERT INTO #tab(i) VALUES (3)'); 
SELECT * FROM #tab; 
-- Invalid object name '#tab'. 

LiveDemo

现在让我们尝试相同的存储过程:

-- Normal procedure 
EXEC ('CREATE PROCEDURE my_proc AS SELECT 1 AS col;'); 
EXEC my_proc; 

-- Global temporary procedure 
EXEC ('CREATE PROCEDURE ##my_proc AS SELECT 2 AS col;'); 
EXEC##my_proc; 

-- Local temporary procedure 
EXEC ('CREATE PROCEDURE #my_proc AS SELECT 3 AS col;'); 
EXEC#my_proc; 

LiveDemo2

问题是为什么本地临时程序的行为不同并且在EXEC以外可见?

+0

FYI:如果对象在tempdb.sys.objects项,我们都能够看到这甚至在scope.querying系统目录后可能提供更多信息 – TheGameiswar

回答

0

因为SQL Server可以重复使用proc的查询计划,所以它保留在exec之外。

只要定义了它的会话(通过exec),proc就会关闭。

MS非常小心地指出temp'tables'(一个带#号)是上下文本地的,对调用程序不可见。

参见: 任何你创建表是在EXEC()的上下文中可见

https://technet.microsoft.com/en-us/library/aa175921%28v=sql.80%29.aspx

+0

您能否提供来自doc的确切报价? '因为SQL Server可以重用proc的查询计划,所以它保留在exec之外。 '带有'WITH RECOMPILE'的SP是什么? – lad2025

+0

引用来自我引用的URL,位于引用页面底部附近的EXEC()一节中。由于SQL Server已经确定,只要调用人员使用“with recompile”激活,它就会保留proc,这将强制SQL Server每次重新编译,但仍然可以在exec之外访问。 –