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

Sql 存储过程中exec中临时表的作用域规则是什么?,sql,tsql,stored-procedures,exec,temp-tables,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 现在,如果我

比较以下存储过程:

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似乎根本不起作用,因为我收到了一条无效的对象名“temp”错误消息

如果源表名是存储过程的一个参数,并且可以具有任意结构,那么为什么会有这种区别,以及如何使用临时表来选择*INTO

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

来自BOL:

本地临时表可见 只有在本届会议上。。。 临时表是自动生成的 当它们超出范围时就会掉下来, 除非使用DROP显式删除 桌子

第一个过程和第二个过程的区别在于,在第一个过程中,表的定义范围与其所选范围相同;在第二种情况下,EXEC在自己的作用域中创建表,因此在本例中选择失败

但是,请注意,以下操作非常有效:

CREATE PROCEDURE [dbo].[testProc3]
AS
    SELECT * INTO #temp FROM information_schema.tables
    EXEC('SELECT * FROM #temp')
GO
CREATE PROCEDURE [dbo].[testProc4]
AS
    EXEC('SELECT * INTO #temp FROM information_schema.tables; SELECT * FROM #temp')
GO
它之所以有效,是因为EXEC的作用域是存储过程作用域的子级。在父作用域中创建表时,它也存在于任何子作用域中

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

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

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