본문 바로가기

Pro*C

[Pro*C 오라클 DB] 호스트 변수 (배열, 구조체)를 이용한 프로그램

Pro*C


#include <stdio.h>
#include <sqlca.h>

EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR uid[20];
    VARCHAR pwd[20];
    int empno[5];
    VARCHAR ename[5][20];
EXEC SQL END DECLARE SETION;

viod main() {
    int end;
    int loopIndex;
    int result;

    strcpy((char *)uid.arr,"userid");
    uid.len = (short)strlen((char *)uid.arr);
    strcpy((char *)pwd.arr,"pwd");
    uid.len = (short)strlen((char *)pwd.arr);
    
    EXEC SQL CONNECT : uid IDENTIFIED BY : pwd;
    
    if (sqlca.sqlcode != 0) {
        printf("아디비번 유효하지 않음");
        exit(0);    
        }
        
    for(;end < 0;) {
        EXEC SQL FETCH EMP
        INTO:empno,:ename;
        
        if (sqlca.sqlcode != 1403 ) {
              printf("펫치 에러 : {%d]\n",  sqlca.sqlcode);
              EXEC SQL ROLLBACK WORK RELEASE;
              exit(0)
        }
       if (sqlca.sqlcode == 1403) end  = 0;
       result = sqlca.sqlerrd[2];
       
       for(loopIndex = 0; loopIndex < result; loopIndex++) {
           printf("EMPNO : {%d], ENAME : [%s]\n",  empno[loopIndex], ename[loopIndex].arr);
       }
       
    }

 

이 상황에서 for 문에 에러가 발생할 수 있다

-> 추출해야하는 데이터가 9개라면 첫번째는 5번을 잘 돌지만

    두번째 루프에서 데이터가 4개이지만 5번을 돌기 때문에

 

추출된 데이터만큼 루프를 수행하도록 만들기 위해 SQLCA를 사용해야함

-> sqlca.sqlerrd[2] 는 추출된 데이터의 건수를 저장하고 있는 변수

 

 

Host Array 를 이용하여 다중행을 출력해보자

#include <stdio.h>
#include <sqlca.h>
#include <stdlib.h>
#include <string.h>

// (1) SQL 변수 정의
EXEC SQL BEGIN DECLARE SECTION;
VARCHAR uid[20];               // 사용자 아이디
VARCHAR pwd[20];               // 비밀번호
int empno[5];                  // 최대 5개의 직원 번호 Host Array
VARCHAR ename[5][20];          // 최대 5개의 직원 이름 Host Array
int row_count;                 // 한 번에 가져올 행 수
EXEC SQL END DECLARE SECTION;

// (2) 커서 선언
EXEC SQL DECLARE EMP CURSOR FOR emp_cursor; // EMP 커서 선언

void main() {
    int end = 1;                   // FETCH 종료 플래그
    int loopIndex;                 // 내부 루프 인덱스

    // (3) 사용자 아이디와 비밀번호 설정
    strcpy((char *)uid.arr, "userid");
    uid.len = (short)strlen((char *)uid.arr);
    strcpy((char *)pwd.arr, "pwd");
    pwd.len = (short)strlen((char *)pwd.arr);

    // (4) 데이터베이스 연결
    EXEC SQL CONNECT :uid IDENTIFIED BY :pwd ;
    if (sqlca.sqlcode != 0) {
        printf("데이터베이스 연결 실패: [%d]\n", sqlca.sqlcode);
        exit(0);
    }

    row_count = 5; // (5) 한 번에 가져올 행의 수 설정

    // (6) 커서 열기
    EXEC SQL OPEN EMP FOR
        SELECT empno, ename FROM employees; // employees 테이블에서 직원 번호와 이름을 가져옴

    // (7) FETCH 반복문
    for (; end > 0; ) {
        // (8) 다중 행 FETCH
        EXEC SQL FETCH EMP
        INTO :empno, :ename;

        if (sqlca.sqlcode != 0 && sqlca.sqlcode != 1403) {
            printf("FETCH 오류: [%d]\n", sqlca.sqlcode);
            EXEC SQL ROLLBACK WORK RELEASE;
            exit(0);
        }

        if (sqlca.sqlcode == 1403) {
            // 더 이상 데이터가 없는 경우 종료
            end = 0;
            continue;
        }

        // (9) FETCH된 데이터 출력
        for (loopIndex = 0; loopIndex < sqlca.sqlerrd[2]; loopIndex++) {
            printf("EMPNO: [%d], ENAME: [%s]\n", empno[loopIndex], ename[loopIndex].arr);
        }
    }

    // (10) 트랜잭션 커밋 및 연결 해제
    EXEC SQL COMMIT WORK RELEASE;
}

 

 

    • Multi-Row Fetch 명령:
      • EXEC SQL FOR :row_count FETCH를 사용하여 한 번에 row_count만큼의 행 데이터를 가져옴
      • 결과적으로 empno와 ename 배열에 여러 행의 데이터가 저장
    • sqlca.sqlerrd[2]:
      • FETCH된 행의 실제 개수
      • 반복문에서 이 값을 사용해 출력할 데이터를 제어
    • Host Array의 역할:
      • int empno[5]와 VARCHAR ename[5][20]은 각각 직원 번호와 이름을 최대 5행까지 저장

Multi-Row Fetch 명령:

다중 행 데이터를 가져오기 위해 EXEC SQL FOR :row_count FETCH 구문을 사용

EXEC SQL FOR :row_count FETCH EMP INTO :empno, :ename;

 

  • :row_count: 한 번에 가져올 행의 개수 (예: 5).
  • :empno, :ename: 가져온 데이터를 저장할 Host Array.

 

FETCH된 데이터 처리:

SQL 구조체 sqlca의 sqlerrd[2]를 사용해 FETCH된 행 수를 확인

for (int i = 0; i < sqlca.sqlerrd[2]; i++) {
    printf("EMPNO: [%d], ENAME: [%s]\n", empno[i], ename[i].arr);
}