存储过程中 exec 中的临时表的作用域规则是什么?
比较以下存储过程:
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。
Compare the following stored procedures:
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
Now, if I run testProc1
, it works, and #temp
seems to only exist for the duration of that call. However, testProc2
doesn't seem to work at all, since I get an Invalid object name '#temp'
error message instead.
Why the distinction, and how can I use a temp table to SELECT * INTO
if the source table name is a parameter to the stored procedure and can have arbitrary structure?
Note that I'm using Microsoft SQL Server 2005.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
来自博尔:
第一个过程和第二个过程之间的区别在于,在第一个过程中,表是在与其选择的范围相同的范围内定义的。在第二个中, EXEC() 在其自己的作用域中创建表,因此在这种情况下选择失败...
但是,请注意以下内容工作得很好:
它之所以有效,是因为 EXEC 的作用域是作用域的子级的存储过程。当表在父作用域中创建时,它也存在于任何子作用域中。
为了给您一个好的解决方案,我们需要更多地了解您要解决的问题...但是,如果您只需要从创建的表中进行选择,那么在子范围中执行选择就可以了:
From BOL:
The distinction between your first and second procedures is that in the first, the table is defined in the same scope that it is selected from; in the second, the EXEC() creates the table in its own scope, so the select fails in this case...
However, note that the following works just fine:
And it works because the scope of EXEC is a child of the scope of the stored procedure. When the table is created in the parent scope, it also exists for any of the children.
To give you a good solution, we'd need to know more about the problem that you're trying to solve... but, if you simply need to select from the created table, performing the select in the child scope works just fine:
您可以尝试使用全局临时表(名为##temp而不是#temp)。但请注意,其他连接也可以看到此表。
You could try using a global temp table (named ##temp not #temp). However be aware that other connections can see this table as well.