디자인상의 문제, 코딩상의 문제, 하드웨어 문제, 비정상적인 값의 입력 등등....
프로그램을 수행하다 보면 다양한 에러들을 접하게 된다. 프로그램을 정상적으로
수행하기 위해서는 이들 에러에 대한 적절한 대책이 필요 한데, 특히 SQL문의
수행과 관련된 에러의 처리는 데이타의 무결성을 유지하고, 정확한 트랜젝션
수행의 기본이 된다. PRO*C에서는 SQL문과 관련된 에러를 처리하기 위한 다양한
방법을 제공하고 있는데, 크게 상태 변수(SQLSTATE, SQLCODE)를 사용하는 방법과 SQLCA를 활용하는 방법으로 나눠볼 수 있다.

1) MODE OPTION값에 따른 ERROR 처리

* MODE = ANSI 일때
SQLSTATE나 SQLCODE중에 하나는 반드시 사용해야 한다.
SQLCA는 선택적이다.
* MODE = ORACLE
SQLCA를 사용해야 한다.
SQLSTATE나 SQLCODE는 선언해도 사용되지 않는다.

2) SQLCODE

SQLCODE는 SQL문을 수행한 STATUS CODE 값을 가지고 있다.
이 변수는 LONG으로 선언해서 사용해야 한다.

< 예제 >
DECLARE SQL BEGIN DECLARE SECTION;
int emp_number, dept_number;
EXEC SQL END DECLARE SECTION;
long SQLCODE;

3) SQLSTATE 상태 변수 (status variable)

SQLCODE와 달리 SQLSTATE는 에러와 warning을 모두 저장하고 있고, character
5자리의 값을 가지고 있다. SQLSTATE를 사용하기 위해서는 반드시 CHAR SQLSTATE[6]; 으로 선언해야 한다.
SQLSTATE 상태 코드는 예외의 유형을 구분해주는 CLASS 두 자리와 구체적인
예외를 말해주는 3자리의 SUBCLASS로 구성된다. 이들 CODE값과 그 의미는 PROGRAMMER*S GIDE TO THE ORACLE PRO*C/C++ PRECOMPILER의 Handling
runtime error편에 자세히 나와 있다.

4) SQLCA(COMMUNICATION AREA)의 사용

SQLCA는 ORACLE COMMUNICATION을 다루는 C STRUCT를 말한다. 이는 상태 코드,
경고 FLAG, 처리된 ROW 수, PARSING ERROR, 기타 에러 메세지에 관한 정보를
담고 있다.


* SQLCA의 선언
EXEC SQL INCLUDE SQLCA; 또는 # include <sqlca.h>

* SQLCA STRUCTURE와 의미
- sqlcaid : identifier
- sqlcabc : SQLCA의 총size
- sqlcode : 최근에 실행된 SQL문의 상태코드
0 에러 없이 정상 수행
>0 SQL문이 수행되기는 했지만 exception이 발생
<0 SQL문 수행 안됨. sqlca.sqlerr[4]로 내용 확인 가능
- sqlerrm : 에러 메세지 길이(sqlerrml)와 메시지 내용(sqlerrmc)
메세지는 총 70자리 까지 밖에 저장되지 않음. 이 이상
의 메세지를 보려면 sqlglm()을 이용해야 한다.(sqlcpr.h
에 정의)
만약 sqlcode가 0일때 sqlerrmc의 내용을 보면 이전에
수행된 에러 메시지가 남아 있으므로 sqlcode < 0일때만
사용하는 것이 바람직하다.

- sqlerrd : SQL문 수행과 관련된 각종 INTEGER정보들
sqlerrd[0], sqlerrd[1], sqlerrd[3], sqlerrd[5]
: 현재 사용하고 있지 않음
sqlerrd[2] : 처리된 row수. cascade를 처리된 row수는 제외됨.
Array processing을 하는 중에 에러가 발생했다면, 이
변수에는 정상적으로 처리된 row의 수를 return하게
된다.
sqlerrd[4] : SQL문에서 parse error가 발생한 지점. ( 0부터 시작)

- sqlwarn : warning flag. 해당 warning 발생시 *W*를 set한다.
sqlwarn[0] : warning 발생 여부 set
sqlwarn[1] : character data의 경우truncated 여부 set
indicator변수를 사용하면 원래의 size 확인 가능.
sqlwarn[2] : NULL 값이 group함수에 사용되었는지를 set
sqlwarn[3] : select한 column과 bind한 column의 갯수가 다른
경우 set
sqlwarn[4] : where절이 없는update, delete문 수행 시 set.
where절이 없이 수행된다는 것은 비정상적인 상황
이기 때문에 warning을 한다.
sqlwarn[5]: EXEC SQL CREATE {PROCEDURE/FUNCTION |
PACKAGE|PACKAGE BODY]문 수행시 컴파일 에러
발생시 set

5) WHENEVER문 사용법

디폴트로 컴파일된 프로그램은 오라클 에러나, warning을 무시하고, 가능하다면
프로그램 수행을 계속한다. 비정상적인 동작에 적절한 조치를 취하기 위해 자동
으로 에러나 warning의 발생을 감지하려면 WHENEVER문을 사용하면 된다.
WHENEVER문의 scope rule은 위치에 의해 결정되는 것이지, logical하게
결정되는 것이 아니라는 점을 주의해야 한다. 그러므로 수행될 SQL 문 이전에
WHENEVER절을 위치하도록 해야 한다. 그리고, 다음 WHENEVER절이 나타나기
이전까지만 효과가 있다.

WHENEVER SQLWARING문을 사용하려면 반드시 SQLCA를 선언해야 한다.

* SYNTAX
EXEC SQL WHENEVER <condition> <action>;
* CONDITION유형
SQLWARNING / SQLERROR / NOT FOUND
* ACTION 유형
- CONTINUE :WHENEVER문을 사용하지 않은 것과 동일한 결과
- DO
- GOTO <label>
- STOP : COMMIT되지 않은 WORK은 모두 ROLLBACK 시킴.

condition과 action을 적절히 혼합하여 사용하면 되는데, 조심해야 할 사항은
WHENEVER SQLERROR GOTO <lable>을 사용할때 무한 loop에 걸리지 않도록 주의
해야 한다. (대신에 WHENEVER SQLERROR CONTINUE를 사용하는 것이 좋다.)

다음은 WHENEVER ...... DO 구문을 사용한 간단한 예제이다.

......
EXEC SQL WHENEVER SQLERROR DO handle_insert_error(*Insert Error*);
EXEC SQL INSERT INTO emp (empno, ename,deptno)
VALUES (:v_empno, :v_ename, :v_deptno);
EXEC SQL WHENEVER SQLERROR DO handle_delete_error(*delete Error*);

......
handle_insert_error(char *stmt)
{
switch(sqlca.sqlcode)
{ case -1 : /*duplicate l\key value */
......
break;
case -1401 : /*value too large*/
......
break;
default : /*do somthing here too*/
........
break;
}
}

handle_delete_error(char *stmt)
{
printf("%s\n\n", stmt);
if ( sqlca.sqlerrd[2] == 0 )
{ /* no rows deleted */
........
}
else
{
......
}
}

원본 http://blog.naver.com/maxntop/120005086625

, .