存储过程调用多个存储过程

时间:2009-11-11 16:00:54

标签: sql-server stored-procedures

为一个存储过程调用多个存储过程时,这是在SQL Server 2008上进行此操作的正确或最佳方法吗?

CREATE PROCEDURE [dbo].[DoStuff]
AS
BEGIN
    SET NOCOUNT ON;
    declare @result int
    BEGIN TRANSACTION
        BEGIN
            EXECUTE @result = dbo.UpdateTHIS @ID = 1            
            IF @result != 0
                ROLLBACK
            ELSE 
                EXECUTE @result = dbo.UpdateTHAT @ID = 21               
                IF @result != 0
                    ROLLBACK
                ELSE
                    EXECUTE @result = dbo.UpdateANOTEHR @ID = 15
                    IF @result != 0
                        ROLLBACK
                    ELSE
                        COMMIT
                        SELECT @result 
        END             
END

3 个答案:

答案 0 :(得分:5)

我强烈建议使用TRY / CATCH块和RAISERROR而不是@@ ERROR / @结果检查。我有一个博客条目,显示如何正确使用事务和TRY / CATCH块,包括嵌套事务只恢复失败的过程调用工作,以便calee可以恢复不同的路径并继续事务,如果它感觉像:{{ 3}}

<强>&LT;更新&GT;

您在程序退货模式方面存在不一致之处。 UpdateTHIS和UpdateTHAT返回0/1作为返回值,而包装器DoStuff作为结果集(SELECT)返回。这意味着您无法编写调用DoStuff的DoMoreStuff,因为它必须使用INSERT ... EXEC来捕获结果,并且您很快就会发现INSERT ... EXEC无法嵌套。为了保持一致性,我建议使用RETURN @result。

&LT; /更新&GT;

我也有一个不相关的推荐,这只是风格的一个元素:我发现很长的IF ...如果......如果......如果......如果...块很难阅读和遵循。我总是发现表达与DO一样...... BREAK ...... BREAK ...... BREAK ...... WHILE(FALSE)更容易阅读。 T-SQL没有DO ... WHILE构造,因此必须使用WHILE ...:

BEGIN TRANSACTION
WHILE (1=1)
BEGIN
  EXECUTE @result = dbo.UpdateTHIS @ID = 1;         
  IF @result != 0
  BEGIN
     ROLLBACK;
     BREAK;
  END 

  EXECUTE @result = dbo.UpdateTHAT @ID = 21             
  IF @result != 0
  BEGIN
     ROLLBACK;
     BREAK;
  END

  ...

  COMMIT;
  BREAK;
END

同样,这并不重要,因为它只是一种代码格式化风格,但如果您同意它会导致代码更容易阅读,那么这是一个建议。

答案 1 :(得分:1)

嵌套ifs与否/嵌套ifs不同。回滚将回滚一个事务,但继续。我有一些显式的RETURN命令来保证,并在你希望代码退出存储过程的时间和地点显而易见。

答案 2 :(得分:-1)

恕我直言,我不认为从一个存储过程调用其他存储过程是一个非常好的主意。如果出现错误,则需要花费大量的时间来确定错误发生的位置。在某些情况下,其他开发人员可能会更改存储过程而不会告诉团队中的任何人可能出错的事情数量太多了。

最好在一个大的存储过程中编写所有sql。

编辑: 它还取决于存储过程的大小。