관리 메뉴

why don't do your best

파워빌더 ADO.NET 연결시 SQLCODE 코드 본문

Programming/PowerBuilder

파워빌더 ADO.NET 연결시 SQLCODE 코드

빅셔 2013. 10. 8. 17:49

파워빌더 11.5 를 환경으로 작업했음을 알려드립니다.

다른 것도 ADO.NET으로 연결하시면 비슷 할거라 생각합니다.

 

 

 

 

자 그럼 본문....

 

 

 

일단 프로시져에서 MS NATIVE 연결 방식으로 연결하면,

 

프로시져에서 에러처리할 경우

 

    RAISERROR (@p_msg, 16, 1)
    return(-1)

 

주로 위와 같은 방법으로 메시지를 날리고, RETURN(-1)로

 

IF SQLCA.SQLCODE <> 0  THEN ......

 

이렇게 에러발생을 검출해 낼 것이다.(이때는 프로시져에서 return(-1)처리한 것때문에 sqlca.sqlcode 에 -1값이 전달된다.)

 

그런데 불행이도 프로시져에서 RETURN(-1)

 

해봤자.... ADO.NET 으로 연결해두면

 

SQLCA.SQLCODE = 0 을 반환한다......

그렇다면 실제 오류가 발생되서 SQLCODE = -1 이 발생되지 않으면.....

프로시져가 정상적으로 처리했는지 처리하지 못했는지..... 알수가 없다.

 

예를들어

 

UPDATE A

SET 컬럼 = 값

FROM ......

WHERE ....

AND 조건

AND 조건

 

IF @@ERROR > 0 OR @@ROWCOUNT = 0

BEGIN

select @p_msg = 'error'

goto End_proc

END

 

 

위와 같은 경우로  UPDATE 행에 꼭 대상행이 있어야 하는 경우

@@ROWCOUNT = 0 을 뱉지만, @@ERROR 도 0 일 것 이다.(에러가 없어서 sqlca.sqlcode 에는 0 상태이다.)

 

그럼 GOTO로

 

 End_proc:
    RAISERROR (@p_msg, 16, 1)
    return(-1)

 

 

이쪽으로 분기되서 -1을 리턴 쳐도 결과는 (DB안에서 실제 에러가 발생했던건 아니니깐,,, sqlcode로 에러를 검출할 수 가 없다.)

SQLCA.SQLCODE = 0 이기때문에

 

IF SQLCA.SQLCODE <> 0 THEN ......

구문으로 는 프로시져의 성공여부를 검출할수 가 없다.  ( 프로시져 실행 뒤에 IF sqlca.sqlnrows <> 0 THEN 이런 건 아예 배제 하겠다. )

 

그래서 에러를 검출하지못하고 프로그램이 다음으로 진행되어

 

커밋 되어버리면 프로시져로 업데이트 된 행은 없는데,,,,

 

다른 트랜잭션 명령어들은 커밋 되어버릴수 있음을 의미한다.

 

( 파워빌더 INSERT,UPDATE 한 행은 정상적으로 처리가 되고

 

프로시져에서 영향을 받아야 할 행은 영향을 안받고

 

커밋 되어버리는 경우 또 간혈적으로 발생해서 왜이런건이 발생하는지 오리무중에 빠져들게 된다.)

 

 

이걸 막는 방법은 자체적으로

 

OUTPUT 파라메터를 사용하는 것이다.

 

 

create              procedure [dbo].[usp_연습]  @p_formcd   char(01),
              @p_workno   nvarchar(20),
              @p_planno   nvarchar(20),
              @p_oldqty_i   numeric(14,2),
              @p_oldqty_o   numeric(14,2),
              @p_col_i    nvarchar(10),
              @p_col_o    nvarchar(10),
              @p_col_p    nvarchar(10),
              @p_mode    char(01),   -- 3:삭제
              @p_entryid   nvarchar(20),
              @p_msg    nvarchar(200),
              @rtn_code   int output  --  이 rtn_code를 output 형태로 파워빌더로 돌려주는 것이다.

 

성공적으로 끝나면

 

SET @rtn_code = 0

RETURN(0)

 

 

 End_proc:
RAISERROR (@p_msg, 16, 1)

set @rtn_code = -1
return(-1)

 

에러로 GOTO문 이때 set @rtn_code = -1 이문장을 전달해서 검출하면 된다.

 

 

하지만.....

 

파워빌더에서

 

DECLARE C1 PROCEDURE FOR usp_연습

 :ls_formcd,:ls_workno,:ls_planno,:p_old_qty1,:p_old_qty2,:p_old_qty3,:p_old_badqty,:is_col_i,:is_col_o,:is_col_p,:p_mode,:gs_userid,:ls_msg,:li_rtn_code output;
EXECUTE C1;

CLOSE C1;

 

이런식으로 해서는 OUTPUT 변수를 받아올수 없다. 아래와 같이 바꿔줘야 한다.

 

 

DECLARE C1 PROCEDURE FOR usp_연습

                @p_formcd = :ls_formcd
                ,@p_workno = :ls_workno
                ,@p_planno = :ls_planno
                ,@p_oldqty_i = :p_old_qty1
                ,@p_oldqty_o = :p_old_qty2
                ,@p_col_i = :is_col_i
                ,@p_col_o = :is_col_o
                ,@p_col_p = :is_col_p
                ,@p_mode = :p_mode
                ,@p_entryid = :gs_userid
                ,@p_msg = :ls_msg
                ,@rtn_code = :li_rtn_code output;
             
EXECUTE C1;
Fetch   C1  InTo  :li_rtn_code;
CLOSE C1;

 

Fetch 로 마지막 @rtn_code의 값을 li_rt_code 로 리턴받는다.

 

 

IF SQLCA.SQLCODE <> 0 THEN ...... 이제 이 구문 처럼

 

IF li_rtn_code <> 0 THEN ......

 

ROLLBACK USING SQLCA; 로 흘려 보내면 되겠다.

 

 

 

혹시나 저처럼 모르셨던 분에게 도움이 되셨으면 합니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Comments