반응형

오류 처리하기

    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

 

 

 

 

반응형
블로그 이미지

자연&사람

행복한 개발자 programmer since 1995.

,