比较以下存储过程:
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。
答案 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)。但请注意,其他连接也可以看到此表。