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

发布于 2024-11-05 22:46:36 字数 567 浏览 2 评论 0原文

比较以下存储过程:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情深缘浅 2024-11-12 22:46:36

来自博尔:

本地临时表可见
仅在当前会话中......
临时表会自动生成
当它们超出范围时掉落,
除非使用 DROP 明确删除

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

但是,请注意以下内容工作得很好:

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

它之所以有效,是因为 EXEC 的作用域是作用域的子级的存储过程。当表在父作用域中创建时,它也存在于任何子作用域中。

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

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

From BOL:

Local temporary tables are visible
only in the current session... ...
Temporary tables are automatically
dropped when they go out of scope,
unless explicitly dropped using DROP
TABLE

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:

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

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:

CREATE PROCEDURE [dbo].[testProc4]
AS
    EXEC('SELECT * INTO #temp FROM information_schema.tables; SELECT * FROM #temp')
GO
伏妖词 2024-11-12 22:46:36

您可以尝试使用全局临时表(名为##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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文