프로그래밍/DB

[DB] MSSQL 저장프로시저 예외처리방법(Try Catch .. throw)

ss-pro 2020. 10. 2. 22:32
반응형

이번에는 저장프로시저 사용시 예외처리방법에 대해 살펴보도록 하겠습니다. 
msdn의 syntax를 살펴보면 아래와 같습니다. 프로그램의 try catch와 유사한것을 볼수 있습니다. 

1
2
3
4
5
6
7
BEGIN TRY  
     { sql_statement | statement_block }  
END TRY  
BEGIN CATCH  
     [ { sql_statement | statement_block } ]  
END CATCH  
[ ; ] 

먼저 MyUser라는 테스트용 데이터베이스를 만들어보겠습니다.

1
2
3
4
5
CREATE TABLE [dbo].[MyUser](
    [id] [int] IDENTITY(1,1NOT NULL PRIMARY KEY,
    [name] [varchar](10NULL,
ON [PRIMARY]
GO 

이제 INSERT처리를 하는 AddMyUser라는 저장프로시저를 만들어 보도록 하겠습니다. 저장프로시저를 만든 후 임의로 에러를 발생시켜보도록 하겠습니다. name필드의 길이값이 10이므로 해당값보다 크게해서 에러를 발생시키도록 하겠습니다. 

1
2
3
4
-- 프로시저생성
CREATE
 PROCEDURE AddMyUser
    @name varchar(100)
AS
insert into MyUser (name) values (@name)
go
-- 프로시저 실행
exec AddMyUser '12345678901'
 

에러가 발생되어서 해당프로시저가 문제가된것을 확인할수 있습니다. 에러발생시의 경우에도 동작을 진행시키고 싶을 경우도 있을겁니다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- 프로시저생성
CREATE PROCEDURE AddMyUser1
    @name varchar(100)
AS
 
begin try
    insert into MyUser (name) values (@name)
end try
begin catch
end catch
go
-- 프로시저 실행
exec AddMyUser1 '12345678901'
 

try catch 문을 사용하면 에러메세지가 나타나지 않고 아래와 같이 0 row affected와 같이 메세지가 나타납니다. 에러메세지가 나타나지 않기때문에 정상처리된것처럼 오해할수 있습니다. 특히 외부 시스템에 제공된프로시저일 경우에는 상대방측에서 정상동작되는것처럼 느껴질수 있으시 주의하셔야합니다. 

예외를 발생시키는 방법은 아주 간단합니다. begin catch구문에 throw 구문을 넣어주면됩니다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
-- 프로시저생성
CREATE PROCEDURE AddMyUser1
    @name varchar(100)
AS
 
begin try
    insert into MyUser (name) values (@name)
end try
begin catch
     throw        -- 예외발생처리
end catch
go
 

throw문을 넣고 실행해보면 아래와 같이 예외 발생된 결과값이 나타나는것을 확인할수 있습니다. 

예외발생 로그기록방법
예외 발생된 부분을 로그로 기록하거나 에러상황별로 좀더 자세히 알고 싶을경우에는 시스템 함수를 이용해서 에러내용을 확인할수 있습니다. 상세에러내용을 로그로 남기거나 S/W상에서 다른 테이블로 남겨놓거나 하여 좀더 세분화 하여 에러내용을 검색해 볼수있을것 같습니다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
-- 프로시저생성
CREATE PROCEDURE AddMyUser1
    @name varchar(100)
AS
 
begin try
    insert into MyUser (name) values (@name)
    RETURN(0)  
end try
begin catch
   
    SELECT  
         ERROR_NUMBER() AS ErrorNumber  
        ,ERROR_SEVERITY() AS ErrorSeverity  
        ,ERROR_STATE() AS ErrorState  
        ,ERROR_PROCEDURE() AS ErrorProcedure  
        ,ERROR_LINE() AS ErrorLine  
        ,ERROR_MESSAGE() AS ErrorMessage;  
    RETURN(-1)
end catch
go
 
/* excute procedure */
DECLARE    @return_value int 
EXEC    @return_value = [dbo].[AddMyUser1]
        @name = N'12345678901' 
SELECT    'Return Value' = @return_value
 
GO

참고)
https://docs.microsoft.com/ko-kr/sql/t-sql/language-elements/try-catch-transact-sql?view=sql-server-ver15