简单的场景。存储过程sp_Task1
调用sp_Task2
,sp_Task2
有一个名为#Task2_Output
的输出临时表。我希望sp_Task1
获取#Task2_Output
并使用它执行进一步的交易。
如何让这两件事发生:
1)确保sp_Task1
等到sp_Task2
完成后再转到下一行代码。
2)如何检查#Task2_Output
中的代码是否已成功创建sp_Task1
。
答案 0 :(得分:0)
由于您没有提到哪个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_Task2返回的返回码。然后,您可以检查sp_Task1中的返回代码,看看是否一切正常。
答案 1 :(得分:0)
接受的答案不正确。
问题1:
确保sp_Task1等到sp_Task2完成后再转到下一行代码。
您无需做任何事情。调用存储过程和函数不是异步的。如果你在sp_Task1中有以下内容:
... other SQL commands
EXEC sp_Task2;
... more SQL commands
然后在sp_Task2;
完成之前不会执行“更多SQL命令”(无论是成功还是由于错误)。
问题2:
如何检查#Task2_Output是否已从sp_Task1
中的代码成功创建
如前所述,一旦子流程(即对#
的调用)结束,子流程中创建的本地临时表(即prefix = sp_Task2
)将不复存在。你可以使用全局临时表(即prefix = ##
),但是sp_Task1
一次只能被一个会话/连接调用,否则你会遇到##Task2_Output
上的名称冲突。但是,只需在sp_Task1
中创建本地临时表即可轻松避免这种情况。必须知道该临时表的名称,因为无论如何sp_Task1
完成后都会在sp_Task2
中访问该临时表。所以没有理由不先创建它:
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]
数据库中检查该proc,然后在本地或指定的数据库中检查该proc。因此,这是一个不必要的性能损失。
使用@@ERROR
/ TRY
结构而非使用CATCH
更有效。