반응형

EXEC SQL WHENEVER를 이용한 오류처리

EXEC SQL WHENEVER ~를 이용한 오류 처리는 Event Handler 방식으로 오류를 처리하는 것으로 <condition>은 Event 종류라고 볼 수 있으며, <action>은 callback이라고 생각하면 됩니다.

 

EXEC SQL WHENEVER <condition> <action>; 

 <condition> : Event 종류 상수로 SQLWARNING, SQLERROR, NOT FOUND 등이 있음

 <action> : Event에 대한 처리 방법

 

Condition 종류

SQLWARNING
  - Warning이 발생하였을 때에 발생하는 Event로 sqlca.sqlwarn[0]에 값이 설정되며, 
   sqlca.sqlwarn[1] ~ sqlca.sqlwarn[7] 중에 값이 설정됩니다.
  - sqlca.sqlcode에는 양수의 값이 설정되며, +1403은 NOT FOUND에서 처리되므로 제외됩니다.
  - SQLWARNING을 사용하기 위해서는 SQLCA에 대해 MODE=ANSI로 설정해야 하며, 
    sqlca.h를 include해야 합니다.

  SQLCA 방식으로 표현하면

  if(sqlca.sqlcode > 0 && sqlca.sqlcode != 1403 && sqlca.sqlcode != 100) {
      <action>;
  }
  과 같습니다.
SQLERROR
    - sqlca.sqlcode의 값이 음수로 설정되었을 때에 발생합니다.

    SQLDA 방식으로 표현하면
    if(sqlca.sqlcode < 0) {
        <action>;
    }
    과 같습니다.
NOT FOUND
    - sqlca.sqlcode == +1403 이거나 +100(MODE=ANSI로 설정했을 때)에 발생합니다.
    - sqlca.sqlcode == +1403인 경우는 SELECT ~ INTO 
      또는 FETCH ~ INTO 절에서 데이터가 return되지 않는 경우입니다.
    - sqlca.sqlcode == +100 (MODE=ANSI로 설정했을 때)인 경우에는
      INSERT ~ SELECT문으로 INSERT된 데이터가 없는 경우입니다.

    SQLDA 방식으로 표현하면
    if(sqlca.sqlcode == 1405 || sqlca.sqlcode == 100) {
        <action>
    }
    과 같습니다.

 

Action 처리 방법

CONTINUE
    - WHENEVER <condition>의 option을 off 시키는 역할을 합니다.

예를들면,
EXEC SQL NOT FOUND DO BREAK;
...
EXEC SQL NOT FOUND CONTINUE;

처럼 위에서 DO BREAK; 설정을 off하여 NOT FOUND 시에 아무 동작을 하지 않도록 합니다.
즉, SQLCA 모드로 변환한다는 의미입니다.
DO handler()
    - handler()는 사용자 정의 함수입니다. 즉, 함수는 직접 구현을 해야합니다.
DO BREAK
    - while()문 또는 for()문 등의 looping문을 빠져나옵니다. 
      주로 FETCH시에 NOT FOUND이면 break;하는 용도로 사용합니다.     
DO CONTINUE
    - while()문 또는 for()문 등의 looping문에서 continue;를 한것과 같습니다.
GOTO lable
    - goto lable; 문을 실행합니다.
STOP
    - rollback을 수행하고 exit()함수를 호출하여 프로그램을 종료합니다. 

 


오류 처리 방법 (WHENEVER vs. SQLCA)

Sample 1-1). WHENEVER SQLERROR로 오류처리 예

int sql_exceute(void)
{
    ......
    
    EXEC SQL WHENEVER SQLERROR error_handler("ORACLE ERROR: ");

    ......

    EXEC SQL  AT :db_con1  INSERT INTO emp (empno, ename, sal, deptno)
    VALUES (:emp_number, :emp_name, :salary, :dept_number);

    /* INSERT 오류 발생하면 error_handler() 함수를 자동으로 실행합니다. */
    ......
}

void error_handler(const char *msg)
{
    // CONTINUE를 반드시 해야 함.
    // EXEC SQL ROLLBACK WORK; 에서 오류가 발생하면 무한 루프가 됨
    EXEC SQL WHENEVER SQLERROR CONINUE; 
    
    ...
    
    /* 오류 처리 로직 */
    
    ...
    EXEC SQL ROLLBACK WORK;
}

 

Sample 1-2). SQLCA로 오류처리한 예

int sql_execute(void)
{
    ......
    
    EXEC SQL  AT :db_con1  INSERT INTO emp (empno, ename, sal, deptno)
    VALUES (:emp_number, :emp_name, :salary, :dept_number);

    if(sqlca.sqlcode < 0) {
        error_handler("ORACLE ERROR: ");
    }

    ....
}
    

void error_handler(const char *msg)
{
    ......
    /* 오류 처리 로직*/
    EXEC SQL ROLLBACK WORK;
} 

 


NOT FOUND 처리 방법 (WHENEVER vs. SQLCA)

Sample 2-1). WHENEVER NOT FOUND처리 예

    EXEC SQL WHENEVER NOT FOUND DO BREAK;

    while(1) {
        EXEC SQL FETCH emp_cursor
        INTO :emp_name, :emp_number, :salary;

        printf("%s - %ld -%ld\n", emp_name, emp_number, salary);
    }
    /* FETCH할 데이터가 없으면 자동으로 break문이 실행되어 printf를 실행하지 않음 */

 

Example 2-2). SQLCA로 NOT FOUND 처리 예

    while(1) {
        EXEC SQL FETCH emp_cursor
        INTO :emp_name, :emp_number, :salary;

        if(sqlca.sqlcode == 1403) {  // 조건에 맞는 데이터가 없으면...
            break;
        }

        printf("%s - %ld -%ld\n", emp_name, emp_number, salary);
    } 

 

 

 

See Also : Pro*C 목차 및 Sample Source

 

 

 

 

반응형

'Oracle > Pro*C' 카테고리의 다른 글

Pro*C 7. Dynamic SQL  (0) 2019.09.25
Pro*C 6. 대량처리 (배열처리)  (0) 2019.09.25
Pro*C 5-1. 오류 처리하기 (SQLCA)  (0) 2019.09.25
Pro*C 4. 기본 SQL문 실행  (0) 2019.09.25
Pro*C 3. 변수선언과 INCLUDE  (0) 2019.09.25
블로그 이미지

자연&사람

행복한 개발자 programmer since 1995.

,