【问题标题】:How to check for output table of called stored procedure?如何检查被调用存储过程的输出表?
【发布时间】:2015-03-17 15:18:40
【问题描述】:

简单的场景。存储过程sp_Task1 调用sp_Task2,而sp_Task2 有一个名为#Task2_Output 的输出临时表。我希望sp_Task1 接受#Task2_Output 并与它进行进一步的交易。

如何让这两件事发生:

1) 确保 sp_Task1 等到 sp_Task2 完成后才能继续执行下一行代码。

2) 如何检查#Task2_Output 是否从sp_Task1 中的代码成功创建。

【问题讨论】:

  • 哪个 dbms? (存储过程实现通常不符合 ANSI。)
  • @jarlh 澄清一下,正如 Whirl Mind 所假设的那样,dbms 实际上是 SQL Server 2005。下次会提前说明。

标签: sql sql-server tsql stored-procedures temp-tables


【解决方案1】:

由于您没有提及哪个 DBMS,我假设它是 SQL Server,因为这些情况通常会出现在那里。

对于问题 1:

在 SQL Server 2005 中,为了让调用存储过程可以访问临时表,您可能必须使用 ##Task2_Output(没错,两个哈希)而不是 #Task2_Output,因为带有两个 # 前缀的临时表名称是有点全局临时表可供调用过程使用,但在最后一次使用后被销毁。但是,如果表名不是动态分配的,您可能需要注意名称冲突。

对于问题 2:

使用 RETURN 语句让 sp_Task2 返回一个返回代码。 如果表创建成功,比如说,返回 1。 如果表创建失败(通过在语句后立即检查@@ERROR 知道),那么,比如说,返回 -99。

在 sp_Task1 中,调用 sp_Task2,如下所示:

Declare @MyRetCode_Recd_In_Task1 int

EXECUTE @MyRetCode_Recd_In_Task1 = sp_Task2 (with calling parameters if any). 

使用 ReturnCode = StoredProcName 方式调用存储过程,sp_Task2 返回的返回码由 sp_Task1 接收。然后,您可以检查 sp_Task1 中的返回码以查看是否一切正常。

【讨论】:

  • 不正确。调用存储过程将可以访问一个常规的单个哈希临时表。
  • @Jeremy 仅当它是由 调用存储过程或调用 it 的某些执行上下文创建的。由调用 存储过程创建的本地#temp 表在该过程退出时被删除。这里的回答者实际上是正确的,因为 99% 的时候有人说,正如 OP 所说,“有一个输出临时表”,他们的意思是一个 由那个创建过程。
  • @WhirlMind 非常有意义!感谢您的回答。
【解决方案2】:

接受的答案不正确。

对于问题 1:

确保 sp_Task1 一直等到 sp_Task2 完成才能继续执行下一行代码。

您无需做任何事情。调用存储过程和函数不是异步的。如果您在 sp_Task1 中有以下内容:

... other SQL commands

EXEC sp_Task2;

... more SQL commands

那么在sp_Task2;完成之前“更多SQL命令”将不会执行(无论是成功还是由于错误)。

对于问题 2:

如何检查 #Task2_Output 是否已从 sp_Task1 中的代码成功创建

如前所述,一旦子进程(即对sp_Task2的调用)结束,在子进程中创建的本地临时表(即前缀 = #)将不复存在。您可以使用全局临时表(即前缀 = ##),但 sp_Task1 一次只能由一个会话/连接调用,否则您将遇到名称冲突##Task2_Output。但这可以通过简单地在sp_Task1 中创建本地临时表来轻松避免。必须知道该临时表的名称,因为无论如何在 sp_Task2 完成后,它将在 sp_Task1 中访问。所以没有理由不先创建它:

CREATE TABLE #Task2_Output (columns...);

... other SQL commands

EXEC sp_Task2;

... more SQL commands

SELECT ...
FROM   #Task2_Output;

然后你无论如何都不需要测试它。


另外:

  • 如果您确实想测试临时表是否存在,请使用以下命令:

    IF (OBJECT_ID(N'tempdb..#Task2_Output') IS NOT NULL)
    BEGIN
      -- non-NULL value from OBJECT_ID() means the table exists
      ..do something;
    END;
    
  • 你真的,真的应该在存储过程名称前加上sp_。该前缀是为系统过程保留的,并由 SQL Server 作为特殊情况处理。它将首先在[master] 数据库中检查该过程,然后在本地或指定的数据库中检查。因此,这是不必要的性能损失。

  • 比起使用@@ERROR,使用TRY/CATCH结构更有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-19
    • 2015-10-15
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    相关资源
    最近更新 更多