如何从内部存储过程回滚和停止执行

时间:2012-07-18 17:43:32

标签: sql-server-2008 tsql sql-server-2008-r2

假设我有两个存储过程OuterInner

CREATE PROCEDURE dbo.Outer
AS
BEGIN
  SET NOCOUNT ON;
  SET XACT_ABORT ON;

  BEGIN TRAN
    EXEC Inner

    -- Perform additional processing (which should not occur if there is 
    -- a ROLLBACK in Inner)
    ...
  COMMIT
END;
GO

Outer存储过程打开XACT_ABORT并启动显式事务。然后它在事务中调用Inner存储过程。

CREATE PROCEDURE dbo.Inner
AS
BEGIN
  DECLARE @Id INT=(SELECT Id FROM SomeTable WHERE ...);

  IF (@Id IS NOT NULL)
    ROLLBACK;

  INSERT INTO SomeTable(...)
  VALUES (...);
END;
GO

Inner存储过程执行检查以查看是否存在某些内容以及是否要回滚在Outer存储过程中启动的整个事务并中止{{1}中的所有进一步处理}和Inner

发生的事情不是我上面所概述的,而是我收到错误消息:

在内心:

  

EXECUTE之后的事务计数表示不匹配的数量   BEGIN和COMMIT语句。先前的计数= 1,当前计数= 0。

在外面:

  

COMMIT TRANSACTION请求没有相应的BEGIN TRANSACTION。

显然,即使启用了XACT_ABORT,Outer也不会停止执行流程。在ROLLBACK之后添加RETURN语句会使我们离开ROLLBACK,但Inner中的执行仍在继续。我需要做些什么才能使Outer停止所有进一步处理并有效退出ROLLBACK

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

发出回滚不会中止批处理(无论XACT_ABORT设置如何)。如果在严重程度足够高的情况下抛出错误 - 系统或通过RAISERROR生成的自定义,批处理将自动中止。

答案 1 :(得分:0)

您必须实施Exception Handling

Begin Try
    Set NOCOUNT ON
    SET XACT_ABORT ON
    Begin Tran
        --Your Code
    Commit Tran
End Try

Begin Catch
    Rollback Tran
End Catch