Pro*C 5-1. 오류 처리하기 (SQLCA)
오류 처리하기
Pro*C에서 실행시 오류가 발생하였을 때에 오류처리하는 방법은 여러가지가 있습니다.
1. SQLCA(SQL Communication Area)를 이용하는 방법
- 오류가 발생하면 struct sqlca sqlca; 전역 구조체 변수에 오류상태를 저장해줍니다
- 오류 여부는 저장된 상태값(오류코드)으로 판단합니다.
2. EXEC SQL WHENEVER <condition> <action>; 을 이용하는 방법
- 직관적이지 않고 잘못사용하면 무한 loop에 빠질 수 있습니다.
- 오류내용은 SQLCA방식으로 확인해야 합니다.
3. ORACA(ORACLE Communication Area)를 이용하는 방법
- 추가적인 시스템 오버헤더가 있으며 거의 모니터링 수준으로 개발자들이 사용하기에는 적합하지 않습니다.
- SQLCA를 기본으로 하고 모니터링할 것이 있을 때에 사용합니다.
SQLCA를 이용하는 방법에 대해서만 알아보겠습니다.
SQLCA (SQL Communication Area)를 이용한 오류처리
SQLCA 방법은 Pro*C에서 SQL문을 수행하는 단계마다 오류가 발생하면 struct sqlca sqlca;라는 전역변수에 오류 상태를 저장하여 줍니다. (C언어의 errno 전역변수와 비슷한 형태 제공)
SQLCA방식을 사용하려면 sqlca.h 파일을 include해야 합니다.
#include <sqlca.h>
또는
EXEC SQL INCLUDE SQLCA;
struct sqlca 구조체의 구조는 아래와 같습니다.
struct sqlca
{
char sqlcaid[8]; /* "SQLCA" 문자열이 저장됨 */
long sqlabc; /* sizeof(struct sqlca) 값*/
long sqlcode; /* 오류가 발생시 oracle error code 저장 */
struct
{
unsigned short sqlerrml; /* 오류메시지 길이 */
char sqlerrmc[70]; /* 오류메시지 */
} sqlerrm;
char sqlerrp[8]; /* 예약됨 */
long sqlerrd[6];
char sqlwarn[8];
char sqlext[8]; /* 예약됨 */
};
struct sqlca sqlca; /* 전역변수 */
sqlca.sqlcode
sqlca.sqlcode에는 오류코드가 저장됩니다. ORA-00001과 같은 오라클의 오류코드 중 ORA를 뺀값을 가집니다.
sqlca.sqlcode == 0
- 정상적으로 처리됨
sqlca.sqlcode > 0
- 조회 또는 INSERT 건수가 없다는 의미입니다.
sqlca.sqlcode == 1403
- 조회된 데이터가 없다는 의미.
sqlca.sqlcode == 100
- INSERT된 데이터가 없다는 의미.(단 컴파일 옵션이 MODE=ANSI 일때)
이 경우는 INSERT - SELECT문에서만 발생함.
sqlca.sqlerrm 구조체
sqlca.sqlerrm.sqlerrml
- 오류메시지의 길이(sqlca.sqlerrm.sqlerrmc에 저장된 문자열의 길이)
sqlca.sqlerrm.sqlerrmc
- 오류메시지 내용.
- 오류메시지는 Null terminate 문자열이 아니므로 반드시 sqlca.sqlerrm.sqlerrml로 크기를 체크해야 함.
- 오류가 잘리지 않고 전체를 보여주려면 sqlglm( )함수를 이용함
sqlca.sqlerrd
sqlca.sqlerrd[0]
- 다른 용도로 예약됨
sqlca.sqlerrd[1]
- 다른 용도로 예약됨
sqlca.sqlerrd[2]
- 처리 건수가 저장됨
- SELECT: 조회 건수
- FETCH : 누적 조회 건수
- INSERT: INSERT 건수
- UPDATE: UPDATE 건수
- DELETE: DELETE 건수
sqlca.sqlerrd[3]
- 다른 용도로 예약됨
sqlca.sqlerrd[4]
- SQL문 파싱시 오류가 발생한 위치 (첫 바이트는 0부터 시작함)
sqlca.sqlerrd[5]
- 다른 용도로 예약됨
sqlca.sqlwarn
slqca.sqlwarn[0]
- 경고 flag W값 설정됨
slqca.sqlwarn[1]
- output data가 truncate됨. indicator 변수를 사용할 경우에 -1 또는 0이 아닌 경우
slqca.sqlwarn[2]
- 사용안함
slqca.sqlwarn[3]
- SELECT 문의 column 갯수와 INTO문의 변수 갯수가 다른 경우
slqca.sqlwarn[4]
- DELETE, UPDATE문에 WHERE절이 없는 경우
slqca.sqlwarn[5]
- 사용안함
slqca.sqlwarn[6]
- 다른 용도로 예약됨
slqca.sqlwarn[7]
- 다른 용도로 예약됨
오류처리 예제
char emp_name[54];
long dept_number;
long salary;
long emp_number;
......
EXEC SQL AT :db_con1 DECLARE emp_cursor CURSOR FOR
SELECT ename, empno, sal
FROM emp
WHERE deptno = :dept_number;
EXEC SQL OPEN emp_cursor;
if(sqlca.sqlcode != 0) {
fprintf(stderr, "CURSOR OPEN ERROR: %.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc);
return -1;
}
while(1) {
EXEC SQL FETCH emp_cursor
INTO :emp_name, :emp_number, :salary;
if(sqlca.sqlcode != 0) { // 오류이면
if(sqlca.sqlcode == 1403) { // 더 이상 조회된 내용이 없는 경우
printf("조회된 데이터가 더 없습니다.\n");
break;
} else {
fprintf(stderr, "%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc);
return -1;
}
}
printf("성명: %s \t사번: %ld \t급여: %f\n", emp_name, emp_number, salary);
}
......
sqlglm( )
- 오류 메시지가 잘리지 않고 상세 오류 메시지를 얻는 함수
#include <sqlcpr.h>
void sqlglm(char *message_buffer, size_t *buffer_size, size_t *message_length);
Pro*C에서 SQL문을 수행 도중 발생한 오류를 sqlca.sqlerrm로 처리 시에 메시지가 잘리는 것 보완하기 위하여 만들어진 함수입니다. (sqlca.sqlerrm의 길이는 최대 70바이트) 오류 메시지는 최대 512바이트이며 이보다 작게 잡을 경우에 잘려질 수 있습니다.
파라미터
message_buffer
- 오류 메시지를 저장할 buffer
buffer_size
- 오류 메시지를 저장하기 위해 할당된 buffer 크기
message_length
- 실제 오류 메시지 길이
RETURN
없음
sqlglm() 사용 예제.
char err_msg[512];
size_t buf_size = 512;
size_t msg_len;
......
EXEC SQL AT :db_con1 INSERT INTO emp (empno, ename, sal, deptno)
VALUES (:emp_number, :emp_name, :salary, :dept_number);
// SQL 수행오류이면
if(sqlca.sqlcode != 0) {
sqlglm(err_msg, &buf_size, &msg_len);
fprintf(stderr, "%.*s\n", msg_len, err_msg);
return -1;
}
See Also : Pro*C 목차 및 Sample Source