2013-05-21 1 views
5

DB2에서 SQL Server 2008R2로 전환하는 과정을 진행하고 있으며 TSQL에 익숙하지 않습니다. 어떤 일이 일어나고 있는지 더 잘 이해하게되면 도움이 될 것입니다.SQL Server 2008R2 RAISERROR를 사용한 중첩 된 트랜잭션

CREATE PROCEDURE RethrowError 
AS 
BEGIN 
    -- Return if there is no error information to retrieve. 
    IF ERROR_NUMBER() IS NULL 
     RETURN; 
PRINT 'yo error'; 

    DECLARE 
     @ErrorMessage NVARCHAR(4000), 
     @ErrorNumber  INT, 
     @ErrorSeverity INT, 
     @ErrorState  INT, 
     @ErrorLine  INT, 
     @ErrorProcedure NVARCHAR(200); 

    -- Assign variables to error-handling functions that 
    -- capture information for RAISERROR. 
    SELECT 
     @ErrorNumber  = ERROR_NUMBER(), 
     @ErrorSeverity = ERROR_SEVERITY(), 
     @ErrorState  = ERROR_STATE(), 
     @ErrorLine  = ERROR_LINE(), 
     @ErrorProcedure = ISNULL(ERROR_PROCEDURE(), '-'); 

    -- Build the message string that will contain original 
    -- error information. 
    SELECT @ErrorMessage = N'Error %d, Level %d, State %d, Procedure %s, Line %d, ' + 
          'Message: '+ ERROR_MESSAGE(); 
PRINT 'yo doin something'; 

    -- Raise an error: msg_str parameter of RAISERROR will contain 
    -- the original error information. 
    RAISERROR 
     (
     @ErrorMessage, 
     @ErrorSeverity, 
     1,    
     @ErrorNumber, -- parameter: original error number. 
     @ErrorSeverity, -- parameter: original error severity. 
     @ErrorState,  -- parameter: original error state. 
     @ErrorProcedure, -- parameter: original error procedure name. 
     @ErrorLine  -- parameter: original error line number. 
     ); 
PRINT 'yo end'; 

    RETURN; 
END 
GO 

우리는 절차가 모든 절차를 터치하지 않고 미래의 오류에 확장 순전히 만든 이유 : 우리는 같은 RethrowError라는 절차를 만들었습니다. 디버깅 목적으로 PRINT 행을 추가했습니다.

내 주요 질문은 우리가 절차 A를 가지고 실패가 RethrowError을 실행하고 나는 메시지 예상대로

yo error 
yo doin something 
yo end 

를 볼 수 있다는 것입니다.

CREATE PROCEDURE dbo.A 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE & SET VARIABLES; 
BEGIN TRY 
    BEGIN TRANSACTION MaintainTarget 

    DO SOME STUFF 
END TRY 
BEGIN CATCH 
    EXEC RethrowError; 

    IF (XACT_STATE()) = -1 
    BEGIN 
     PRINT 
      N'The transaction is in an uncommittable state. ' + 
      'Rolling back transaction.' 
     ROLLBACK TRANSACTION; 
    END; 


    IF (XACT_STATE()) = 1 
    BEGIN 

     PRINT 
      N'The transaction is committable. ' + 
      'Rolling back transaction.' 
     ROLLBACK TRANSACTION; 
    END; 

    RETURN -101; 
END CATCH; 
RETURN; 
END 

GO 

그러나, 우리는 많은 절차를 실행하고 절차를 만들었습니다 (즉, 절차 A는 프로 시저 B에 의해 호출되는) 중첩 된 절차는 내가

yo error 
yo doin something 

을 '입니다 볼 수있는 유일한 메시지를 실패 할 때 마지막 메시지가 더 이상 나타나지 않는 이유를 이해하지 못합니다.

절차 B는 절차 A와 유사하지만 캐치가 약간 다릅니다.

CREATE PROCEDURE dbo.B 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE & SET VARIABLES; 
BEGIN TRY  
    DO SOME STUFF 
END TRY 
BEGIN CATCH 
COMMIT; 

RETURN -101; 
END CATCH; 
RETURN; 
END 

어떤 일이 일어나고 있는지 더 잘 이해할 수 있도록 도와 주시면 감사하겠습니다.

답변

3

필자는 코드 작성을 모방하여 코드를 편집 할 수 있었지만 단순하게 유지했다 (사실, 실제로;).

RethrowError 프로 시저가 procA의 CATCH 블록 내부에서 호출되어 모든 것이 실행되기 때문에 procA가 정상적으로 작동합니다. 그러나 두 번째 경우에는 여전히 procB의 블록 안에 있습니다. 따라서 procB의 CATCH 부분은 RethrowError의 RAISERROR가 호출 된 직후에 발생합니다. 여기

begin try 
    select 1/0 
    print 'doesnt show - div error' 
end try 
begin catch 
    print 'oops' 
    select 1/0 
    print 'this one shows because its in CATCH!' 
end catch 

그리고 당신의 단순화 된 코드입니다 :이 도움이

-- "proc B" start 
begin try 
    -- "proc A" start (works fine alone) 
    begin try 
     begin tran 
     select 1/0 --error 
    end try 
    begin catch 
     print 'yo error'; 
     RAISERROR ('RE from RethrowError', 16, 1) --comment this out and see what happens 
     print 'yo end'; 

     IF (XACT_STATE())=-1 or (XACT_STATE())=1 
     BEGIN 
      PRINT N'Rolling back transaction.' 
      ROLLBACK TRANSACTION; 
     end 
    end catch -- "proc A" ends 
end try 
begin catch 
    select error_message(), error_severity(), error_state() -- 
    print 'outer catch'; 
    commit; 
end catch; 

희망

이 간단한 예는 TRY-CATCH의이 동작을 보여줍니다.

+1

+1. SQL Server 2008의 중첩 오류 처리기 (http://dba.stackexchange.com/q/23805/5203)와 조심하여 추가하십시오. – GSerg

+0

감사합니다. 지금 완전히 명확합니다. 나는 일을 더 단순하게하기 위해 명심해야 할 것이다. :). – jabrown

관련 문제