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

pol*_*nts 4 sql t-sql 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
Run Code Online (Sandbox Code Playgroud)

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

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

请注意,我正在使用Microsoft SQL Server 2005.

Mic*_*son 6

来自BOL:

本地临时表仅在当前会话中可见... ...临时表在超出范围时会自动删除,除非使用DROP TABLE显式删除

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

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

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

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

为了给你一个很好的解决方案,我们需要更多地了解你要解决的问题......但是,如果你只需要从创建的表中进行选择,那么在子范围内执行select就可以了. :

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