본문 바로가기

MSSQL/SQL Server 2005 new Feature

Try Catch에 대한 고찰...


안녕하세요 Ancia입니다. ㅋ

사실 이번 포스팅은 두근두근하네요 ^^; MSSQL의 파트에 첫글입니다. (사실은 쥐뿔도 모르지만서도..^^)


이리저래 하다가 Try-Catch문을 하게되었는데 보니..
인터넷을 찾아서 여러가지 예문을 보다보니 "머야~ 예외처리잖아!!" 라는 생각이 들더군요 ㅋㅋ

사실 학교댕길때 JAVA수업을 들었던 적이 있었는데 그와 비슷... 아니 거의 똑같다는 생각이 들더군요

그럼 이제부터 한번 파헤쳐 보도록 하겠습니다.

Try Catch의 정확한 Syntex라고 해야되나요 ㅋ 문법입니다. ㅋ
BEGIN TRY
   ...
END TRY
BEGIN CATCH
  ...
END CATCH


위와 같이죠 ^^;; 매우 심플하고도 강력하게 보입니다. 즉 if문이나 case문과 같이 사용하면 되겟는데요
가장 큰 차이점은 멀까요?

네 바로 일정한 처리 구문 전체에서 에러가 발생할때 특정한 Text나 해당 에러의 넘버를 뱉는것이지요

이것이 바로 2000과 가장 큰 차이점입니다. 2000에서는 Try Catch문이 없지만 위와 같이 if문이나 case,
GOTO문 등을 사용해서 각 처리의 한 라인마다 오류가 발생할 것에 대비하여 에러처리 구문을 기입했다는
것이지요 ㅋ

그럼 한번 볼까요 ^^;

먼저 본 포스팅의 목적이자 2005의 신기능인 Try-Catch의 예제입니다.

begin
DECLARE @I INT

BEGIN TRY
 SET @I = 10 / 0
END TRY
BEGIN CATCH
 SET @I = 0 
 PRINT '에러번호 : ' + CAST(error_number() as varchar)
 PRINT '에러메시지 : ' + error_message()
 PRINT '에러심각도 : ' + CAST(error_severity()as varchar)
 PRINT '에러행번호 : ' + CAST(error_line() as varchar)
 PRINT '에러 프로시저 : ' + ISNULL(error_procedure(), '없음')
 /*
 if ERROR_NUMBER() = 8134 
 BEGIN
  print '나눗셈 에러(0으로 나눔)'
 END 
 */
END CATCH
end


결과는

이렇지요

그럼 2000에서는 어떻게 쓰이는지 보도록 하겠습니다.
 
ALTER PROC p_name (@i INT)
AS
BEGIN 
 DECLARE @r_Message nvarchar(max)
             , @r_reSeverity int
             , @r_reState int

 IF (@i = 0)
   BEGIN
      SET @r_Message =  '0으로 나누기 오류가 발생했습니다.'
      SET @r_Severity = 16
      SET @r_State = 1
      
       print "에러번호 8134"
       print "에러 심각도 : 16"
       print "에러 발생 프로시저명 p_name"
       print @r_message

       RAISERROR(@rMessage,@r_Severity,@r_state)
   END
 ELSE
   PRINT 1 / @i
END

또다른 방법으로는

ALTER PROC p_name (@i INT)
AS
BEGIN 
 DECLARE @r_Message nvarchar(max)
             , @r_reSeverity int
             , @r_reState int

PRINT 1 / @i

IF (@@ERROR !=0)
  BEGIN
      SET @r_Message =  '0으로 나누기 오류가 발생했습니다.'
      SET @r_Severity = 16
      SET @r_State = 1

       print "에러번호 8134"
       print "에러 심각도 : 16"
       print "에러 발생 프로시저명 p_name"
       print @r_message
  END
END

EXE p_name


흐미.. 타이핑하기 귀찮군요 ㅋㅋ :D
그럼 위의 2005에서의 Try Catch와 2000버전의 IF문을 이용한 처리를 보면
확연한 차이가 보이지요

2000에서는 에러의 발생이 어떤건지 정확히 모른다는것지요 바로 해당 코드의 작성자가 직접 에러처리를 손으로 써줘야하는 불편함이 있습니다.

그리고 Try Catch의 경우 Tryr구문(Begin try ~ End Try)에서 진행되는 구문에대해서 오류를 처리하는것에 비해
2000에서는 일일이 오류를 캐치하는 구문을 만들던지 아니면 예상되는 에러가 발생할 것을 대비하여 아래에 부비트랩(if문)을 설치하는 차이가 발생하죠 딱~ 봐도 Try Catch가 강력해 보이지요 ^^;;

헐퀴.. 쓰다보니 엄청 길어졌습니다만, 대부분이 코드이기때문에 몇가지 더 조사해 보도록 하겠습니다.

앞서 Try Catch에서 사용된 함수들이 있는데요 정리를 하면

                  오류함수                          설명
           ERROR_NUMBER()                      에러번호
          ERROR_MESSAGE()                     에러 메시지
         ERROR_SERVERITY()                     에러 심각도
            ERROR_STATE()                       에러 상태
             ERROR_LINE()                  에러 발생 행번호
        ERROR_PROCEDURE()            에러 발생 프로시저명or 트리거

대충 쭉~ 읽어보면 흠흠흠.. 이라는 두뇌스케닝이 읽어나지요. 그르나 보다보면 "에러 심각도"라는 녀석이 있습니다. 이녀석이 하는 역할은 미리 정해놓은 0~ 24번까지의 에러 번호를 매겨서 뱉는것이지요 ^^;

그럼 그 정보는 어디있느냐 바로 "SP_ADDMESSAGE"에 들어 있지요 ^^;
물런 에러의 내용도 수정할 수 있습니다. (소개와 수정법은 스크롤 압박으로 패스하도록 할께요 중요한것은 영문에러와 한글에러 중 우선검색이 영문에러가 되니 영문이 반드시 있어야하는거 있지마시구요~)

그럼 이 좋은 Try Catch를 어디다 쓸까.. 네~ 대부분은 상기와 같이 에러 검출을 위해 사용합니다만,
우리는 DBA이기에 TRANSACTION처리에 적용할 수 있겠지요 ㅋㅋ
에러가 발생했을 경우 SET XACT_ABORT ON을 사용하여 트랜젝션을 중지 할 수 있습니다.

이부분은 나~~ 중에 트랜젝션에 대한 포스팅때 추가 설명해드리도록 하지요 쿠쿠쿠~
(절대 지금 몰라서 그런거 아닙니다. 큭..orz)

[보너스]
어떠한 상황이 정상 적으로 처리가 되는게 맞지만 프로시져에서 혹은 DB에서 그러한 값이 입력 혹은 동작이 못하게 해야할 경우가 간혹 생깁니다. (헉.. 없다면.... 대략 언젠가는 생길것 같습니다. ㅋㅋ)

이때 쓰는 녀석이 바로 RAISERROR입니다.
 (네 네이밍센스 작렬이죠 말그대로 에러를 고의적으로 일으키는 녀석이라는 말씀!!)

눈치빠르신분들은 이미 이 글이 나오기 전에 살펴 보셨으리라 생각되는군요~
네~~ 바로 앞서 살펴본 2000에서의 try catch 구문에서 사용된 녀석이지요~~

syntex는 아래와 같습니다.
RAISERROR ( {msg_id | msg_str | @local_variable }
    { , severity, state }
    [ ,argument [ , ...n] ] )
    [ WITH option [ , ...n] ]


흠.. 당췌 먼말인지 모르겠네요 예제를 볼까요 ^^;;
DECLARE @I INT

BEGIN TRY
  SET @I = 10 / 0
END TRY
BEGIN CATCH
  RAISERROR (N'긴급 에러 발생 %s 프로시저%d 줄.' -- 메시지 내용
                     , 10 -- 중요도
                     , 1 -- 상태
                     , N' Student' -- 첫번째인자
                     , 25) -- 두번째 인자
                     with log;
END CATCH

TIP. 에러 처리의 경우 심각도가 20번 이상의 경우 제어가 넘어오지 않으므로 그 이하의 에러를 발생시켜 처리해야합니다.

간단히 정리하면 Try Catch의 장점은

1. 에러 발생시 각종 에러에 대한 정보를 자동으로 검출하여 출력한다.
2. 여러 구문을 묶어서 에러 처리를 유도하여 동일한 검출 라인이 필요하지 않다
3. 이를 활용하여 transaction 처리에 활용할 수 있다.


헐헐 정리하다보니 꽤 길었네요 그럼 다음에 또 뵙도록 하겠습니다. ㅋ
긴글 읽어주시느라 감사합니다.

내공이 부족하네요 ㅠ.ㅠ 아~ MSSQL의 길은 험난하군요!!