2016-12-22 4 views
1

'테스트 오류'를 실행하면 예기치 않은 결과가 발생합니다. @@Trancount을 확인하면 불일치를 피할 수 있다고 생각했습니다. 누구든지 오류를 롤백하는 더 나은 방법으로 나를 도울 수 있습니까? 중첩 된 모든 트랜잭션을 롤백하고 싶습니다. 저장 프로시 저는 자체적으로 중첩 될 수 있습니다.롤백이있는 경우 이러한 중첩 SQL Server 트랜잭션이 불일치 오류를 발생시키는 이유는 무엇입니까?

alter procedure TestErrors 
as 
begin 
    begin try 
     begin transaction 

     exec TestErrorsInner; 

     IF @@TRANCOUNT > 0 
      commit transaction; 
    end try 
    begin catch 
     IF @@TRANCOUNT > 0 
      rollback transaction; 
     select ERROR_MESSAGE(); 
    end catch 
end 

alter procedure TestErrorsInner 
as 
begin 
    begin try 
     begin transaction 

     RAISERROR('Test Error',16,1); 

     IF @@TRANCOUNT > 0 
      commit transaction; 
    end try 
    begin catch 
     IF @@TRANCOUNT > 0 
      rollback transaction; 
     select ERROR_MESSAGE(); 
    end catch 
end 

결과 :

테스트 오류

거래 횟수 후 EXECUTE는 의 불일치 번호 BEGIN 및 COMMIT 문을 나타냅니다. 이전 개수 = 1, 현재 개수 = 0

+0

참조 : [SQL Server DBA 신화 - 중첩 트랜잭션이 실제로 발생했습니다] (http://www.sqlskills.com/blogs/paul/a-sql-server-dba-myth-a-day-2630) -nested-transactions-are-real /) –

답변

1

이것은 액티브 상태가 아닌 TestErrors에서 트랜잭션을 포착하기 때문입니다.

블록 Catch 블록에 이미 트랜잭션을 롤백했습니다. 그런 다음 다시 시도 할 COMMIT/ROLLBACKTestErrors에 있습니다. 그래서 그것은 오류를 던지고있다.

블록의 Catch 블록에서 오류를 다시 명시 적으로 제기하는 것은 사용자의 책임입니다. 그래서 그 Error는 부모 SP에 대한 입력이 될 것입니다.

ALTER PROCEDURE TESTERRORSINNER 
AS 
BEGIN 
    BEGIN TRY 
     BEGIN TRANSACTION 

     RAISERROR('TEST ERROR',16,1); 

     IF @@TRANCOUNT > 0 
      COMMIT TRANSACTION; 
    END TRY 
    BEGIN CATCH 
     IF @@TRANCOUNT > 0 
      ROLLBACK TRANSACTION; 
     --SELECT ERROR_MESSAGE(); 
     RAISERROR('TEST ERROR in Catch',16,1); --Here Raised 
    END CATCH 
END 

는 이제 TestErrors 저장 프로 시저를 실행처럼

그래서 당신의 TestErrorsInner가 있어야합니다, 당신은 오류가 발생하지 않습니다.

그리고 당신의 결과를 줄 것이다 XACT_STATE()를 호출 XACT_STATE()

와 트랜잭션 상태를 확인할 수 있습니다 0 또는 1 또는 -1,

  • 1이면 (MSDN에서) 트랜잭션이 커미터이다.
  • -1이면 트랜잭션을 커밋 할 수 없으므로 롤백해야합니다.
  • XACT_STATE = 0이면 트랜잭션이없고 커밋 또는 롤백 작업으로 인해 오류가 발생 함을 의미합니다.
+0

SP가 직접 호출되거나 다른 SP 내에 중첩 될 수 있으므로 외부 SP에 catch 블록에 RAISERROR가 없도록하려면 어떻게해야합니까? – Tom

+0

IF @@ TRANCOUNT> 1 RAISERROR ..; @@ TRANCOUNT> 0 ROLLBACK TRANSACTION이라면? – Tom

관련 문제