存储过程中exec中临时表的作用域规则是什么?

时间:2011-05-10 19:04:00

标签: sql tsql stored-procedures exec temp-tables

比较以下存储过程:

CREATE PROCEDURE testProc1
AS
    SELECT * INTO #temp FROM information_schema.tables
    SELECT * FROM #temp
GO

CREATE PROCEDURE testProc2
AS
    EXEC('SELECT * INTO #temp FROM information_schema.tables')
    SELECT * FROM #temp
GO

现在,如果我运行testProc1,它就会起作用,并且#temp似乎只在该调用期间存在。但是,testProc2似乎根本不起作用,因为我收到了Invalid object name '#temp'错误消息。

为什么区别,如果源表名是存储过程的参数并且可以具有任意结构,如何将临时表用于SELECT * INTO

请注意,我使用的是Microsoft SQL Server 2005。

2 个答案:

答案 0 :(得分:6)

来自BOL:

  

可以看到本地临时表   只在当前的会议......   临时表是自动的   当他们超出范围时掉线,   除非使用DROP显式删除   表

第一个和第二个过程之间的区别在于,在第一个过程中,表的定义范围与从中选择的相同;在第二种情况下,EXEC()在其自己的范围内创建表,因此在这种情况下选择失败...

但请注意,以下工作正常:

CREATE PROCEDURE [dbo].[testProc3]
AS
    SELECT * INTO #temp FROM information_schema.tables
    EXEC('SELECT * FROM #temp')
GO

它的工作原理是因为EXEC的范围是存储过程范围的子级。在父作用域中创建表时,它也适用于任何子项。

为了给您一个很好的解决方案,我们需要了解您正在尝试解决的问题...但是,如果您只需要从创建的表中进行选择,那么在子范围内执行select工作得很好:

CREATE PROCEDURE [dbo].[testProc4]
AS
    EXEC('SELECT * INTO #temp FROM information_schema.tables; SELECT * FROM #temp')
GO

答案 1 :(得分:0)

您可以尝试使用全局临时表(名为## temp而不是#temp)。但请注意,其他连接也可以看到此表。