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

esj*_*sjr 0 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
Run Code Online (Sandbox Code Playgroud)

Rem*_*anu 5

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

<更新>

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

</更新>

我也有一个不相关的推荐,这只是风格的一个元素:我发现很长的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
Run Code Online (Sandbox Code Playgroud)

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