0

假设我有两个存储过程,Outer并且Inner

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所有进一步处理。InnerOuter

发生的事情不是我所期望的,而是我收到了错误消息:

在内部:

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

在外:

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

显然,ROLLBACK即使打开了 XACT_ABORT 也不会停止执行流程。在 之后放一条RETURN语句ROLLBACK让我们退出Inner,但Outer继续执行。我需要做什么才能ROLLBACK停止所有进一步的处理并有效地导致退出Outer

谢谢你的帮助。

4

2 回答 2

1

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

于 2013-01-25T17:31:06.870 回答
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
于 2012-07-19T18:26:04.993 回答