database.sarang.net
UserID
Passwd
Database
DBMS
MySQL
PostgreSQL
Firebird
ㆍOracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
Oracle Tutorials 9021 게시물 읽기
 News | Q&A | Columns | Tutorials | Devel | Files | Links
No. 9021
Pro*C 란? (I)
작성자
정재익(advance)
작성일
2001-12-25 11:50
조회수
8,215

이글은 초보자를 위한 것으로 Pro*C란 무엇인가를 설명해 놓은 것일 뿐입니다. 그냥 참조만 하시기 바랍니다.

원본 출처 : http://home.bcline.com/hoya1/

 

1.1 Pro*C란?

 

ORACLE RDBMS에 준비된 Pro*C툴은, SQL문을 포함한 C 프로그램을, ORACLE 데이터베이스내에 있는 데이터에 접근과, 조작을 할 수 있는 C 프로그램으로 변환하기 위한 것이다. Pro*C는 프리컴파일러이기 때문에, 입력 파일 내에 있는 EXEC SQL 문을 적당한 ORACLE 콜로 변환해서 출력 파일을 작성한다. 그 다음 이 출력 파일을 C 프로그램에 대한 통상의 방법으로 컴파일하고 링크해서 실행모듈을 작성한다.

 

 

1.2 개요

 

Pro*C 툴을 사용하면 프로그램머는 통상의 프로그래밍 과정에 덧붙여서 별도의 처리를 수행 할 필요가 생긴다. 그러나 별도의 처리를 추가함으로써, 프로그램머에 도움이 되는 상당량의 작업을 Pro*C 툴이 수행하게 된다.

 C 프로그램을 작성해서 기동할 때의 통상의 작업 순서는 다음과 같다.
       1. C 프로그램을 작성한다.
       2. 프로그램을 컴파일해서 오브젝트 파일을 작성한다.
       3. 오브젝트 파일을 링크해서 실행 가능한 파일을 작성한다.
       4. 프로그램을 실행한다.

  프로그래머가 소스프로그램에 Pro*C 문을 짜넣는 경우는, 위에서 기술한 순서에 
   한가지 처리가 더 추가된다.
       1. Pro*C 프로그램을 작성한다.
       2. Pro*C를 이용해서 프로그램을 프리컴파일 한다.
       3. 프로그램를 컴파일해서 오브젝트 파일을 작성한다.
       4. 오브젝트 파일을 링크해서 실행 가능한 파일을 작성한다.
       5. 프로그램을 실행한다.

 

1.2.1 C 커맨드 및 SQL 문의 혼합

올바른 SQL 문이면 C 프로그램에서 실행할 수 있다. Pro*C 프로그램에서는 필수의 구성요소나 문장이 몇 개정도 있는 것 외에 기본적인 "지정순서"가 있지만, C 프로그램내의 어디에 배치해도 좋다

 

1.2.2 커맨드의 접두사 EXEC SQL

SQL 문을 호스트 언어에 포함시킴으로써, 발생할 수 있는 언어상의 장애를 최소화하기 위해서, 모든 SQL 문에는 EXEC SQL 이라고 하는 접두사를 붙인다.

 

1.2.3 커맨드의 접두사 EXEC ORACLE

대부분의 Pro*C 문에는 EXEC SQL 이라는 접두사를 붙이지만 EXEC ORACLE 이라는 접두사를 붙인문도 있다. 이들의 문은 SQL과는 호환성이 없고, ORACLE 프리컴파일러 특유의 것이다.

 

1.2.4 SQL 실행문 및 선언문

Pro*C 프로그램에 포함되어 있는 SQL 문은, 실행문 혹은 선언문중의 하나로 분류할 수 있다. 실행문 혹은 선언문에 관계없이 문에는 모두 EXEC SQL 이라는 접두사가 붙는다.

 

 실행문

 

실제로 데이터베이스에 대한 콜을 행성하는 SQL 문이다. 데이터조작문(DML), 데이터정의문(DDL), 데이터제어문(DCL) 등이 있다. SQL 실행문을 실행한 후, SQLCA(SQL 통신영역)에는 일련의 리턴코드가 저장된다.

논리적인 작업단위는, 최초의 SQL 실행문을 실행함으로써 시작된다. 그러므로 CONNECT, COMMIT, ROLLBACK WORK 문의 다음에 첫 번째로 나타나는 SQL 실행문부터 논리적인 작업단위가 새롭게 시작된다.

 

 선언문

 

코드를 생성하지 않기 때문에 논리적인 작업단위에 영향은 없다.

 

1.2.5 Pro*C 프로그램의 구성

Pro*C 프로그램은 2개의 부분으로 구성되어 있고, Pro*C의 처리에는 양자가 모두 필요하다.

 

 어플리케이션 프롤로그

 

변수를 정의하고, Pro*C 프로그램을 위한 일반적인 준비를 수행한다.

 

 어플리케이션 본체

 

ORACLE 데이터를 조작하기 위한 INSERT나 UPDATE 등의 SQL 문을 포함한다. Pro*C가 처리시 필요로 하는 코드의 전후에 어떠한 C 코드를 지정해도 상관없다.

 

2.1 어플리케이션 프롤로그

 

** 선언절

** INCLUDE SQLCA 문

 ** CONNECT 문

 

2.1.1 선언절 ( 2.0 버젼 이후 없어도 상관 없음 )

C 프로그램내에서 사용된 모든 호스트 변수를 선언한다. 선언절은 아래의 문으로 시작한다.

 

EXEC SQL BEGIN DECLARE SECTION;

아래의 문으로 종료한다.

EXEC SQL END DECLARE SECTION;

위 두 개의 문 사이에 허용되는 문은 호스트 변수 또는 표지 변수를 선언하는 문 뿐이다.

 

**호스트 변수

SQL 문 및 프로그램 문의 양쪽으로부터 참조되는 모든 값에 대해서 선언해야 한다. 호스트 변수의 데이터타입은 선언절에서 호스트 언어를 사용해서 선언해야 하며, 이 때 이 데이터타입은 테이블을 정의할 때에 사용되는 ORACLE 데이터타입과 일치할 필요는 없다.

 

EXEC SQL BEGIN DECLARE SECTION;

int pempno; /* 사번 */

char pname[11]; /* 성명 */

int pdeptno; /* 부서 */

EXEC SQL END DECLARE SECTION;

 

EXEC SQL SELECT deptno, ename

INTO :pdeptno, :pname

FROM emp

WHERE empno = :pempno;

 

호스트 변수의 조건

~선언절에서 명시적으로 선언한다.

~선언한 대로 영어 대문자/소문자의 포맷을 사용한다.

~SQL 문에서는 앞에 콜론(:)을 붙인다.

~C 문에서는 앞에 콜론을 붙이지 않는다.

~SQL의 예약어를 사용해서는 안된다.

~상수를 사용할 수 있는 곳에서만 사용한다.

~표지 변수가 붙어 있어도 상관없다.

 

**표지 변수

선언절에서 선언된 호스트 변수에 1대 1로 대응되는 임의 선택 변수이다. 표지 변수는 주로 널 값을 취급하는데 유효하다

표지 변수의 조건

~선언한 대로 영어 대문자/소문자의 포맷을 사용한다.

~2바이트 정수로써 선언해야 한다.

~SQL 문에서는 앞에 콜론(:)을 붙인다.

~C 문에서는 앞에 콜론을 붙이지 않는다.

~SQL의 예약어를 사용해서는 안된다.

~SQL 문 내에서는 대응하는 입력 호스트 변수를 앞에 붙여 사용한다.

 

호스트 변수로서의 포인터 선언

포인터 변수는 C에서 통상적으로 행하는 방법으로 선언함으로써, 선언절내에서 사용할 수 있다.

EXEC SQL BEGIN DECLARE SECTION;

int I, j, *intptr;

char *cp;

EXEC SQL END DECLARE SECTION;

 

SQL 문에서 사용하는 경우는 별표가 아닌 콜론(:)을 변수명 앞에 붙인다.

SELECT intfield INTO :intptr FROM…;

 

VARCHAR 의사타입의 선언

Proc*C에서는 VARCHAR 의사타입을 사용할 수 있으므로, 가변 길이의 문자열을 처리할 수 있다. VARCHAR 의사타입은 선언절에서 참조할 뿐이고, 확장된 C 타입 또는 사전에 선언된 구조라고 생각할 수 있다.

EXEC SQL BEGIN DECLARE SECTION;

VARCHAR jobDesc[40];

EXEC SQL END DECLARE SECTION;

 

이 선언은 다음의 구조체로 확장할 수 있다.

struct {
    unsigned short int len;
    unsigned char arr[40];
} jobDesc;

 

2.1.2 SQL 통신영역의 선언

 

어플리케이션 프로롤로그내에서 SQL 통신영역(SQLCA)에 대한 참조를 포함시킴으로써 각 Pro*C 프로그램에서 발생하는 상황처리를 가능하게 하는데, 유저는 다음의 문을 지정하면 된다.

 

EXEC SQL INCLUDE SQLCA;

 

Pro*C는 프리컴파일시에 SQLCA 파일의 위치를 알아야 한다. 때문에 유저는 다음의 3가지중 하나를 선택해야 한다.

 ~~"INCLUDE = " 커맨드 라인 옵션을 사용한다.

 ~~Pro*C가 파일을 SYS$ORACLE:SQLCA(VMS의 경우)처럼 공동의 OS영역에서 발견할 수 있도록 파일의 정식 명칭을 지정한다.

 ~~PCC를 호출할 디렉토리 또는 디스크에 SQLCA를 카피한다.

 

SQLCA는 다음과 같은 정보를 포함하고 있다.

 경고 플래그와 처리상황에 관한 정보

 에러 코드

 진단 정보

디폴드 값으로서, Pro*C는 가능한한 에러를 무시하고 처리를 속행시킨다. SQLCA내에 포함된 변수를 사용함으로써, 프로그래머는 각각의 환경에서 실행해야 할 처리를 제어할 수 있다.

 

2.1.3 ORACA(SQLCA에 대한 확장)

 

ORACA를 사용하기 위해서는 EXEC SQL INCLUDE을 사용해서 ORACA의 정의를 참조하거나 커맨드라인 옵션 또는 EXEC ORACLE OPTION에서 ORACA = YES 옵션을 선택하여야 한다.

 

2.1.4 ORACA 내의 정보

  현재의 SQL 문의 텍스트(orastxt)
  ORACLE RDBMS가 해석한 문의 내용을 조사할 수 있다. (CONNECT, FETCH, COMMIT등 은 제외)
  ~에러가 있는 파일의 이름(orasfnm)
  ~에러가 있는 행의 번호(oraslnr)
  ~SQL 문 보존 플래그(orastxtf)
        이 플래그를 설정함으로써 어느 조건으로 문을 보존할 지를 선택할 수 있다.
          0. 디폴트값. SQL 문을 보존하지 않는다.
          1. SQLERROR가 있는 SQL 문 만을 보존한다.
          2. SQLERROR 및 SQLWARN이 있는 문을 보존한다.
          3. SQL 문을 전부 보존한다.

    ~DEBUG 처리의 사용 허가 플래그
         이 플래그는 0이나 1을 설정할 수 있다. 
         1을 설정한 경우는 모든 DEBUG 처리를 사용할 수 있다.
      커서 캐쉬 검사(orahchf)

2.1.5 ORACLE에의 접속

 

EXEC SQL CONNECT :oracleid IDENTIFIED BY :oraclepassword;

 

 CONNECT 문은 Pro*C 프로그램 내에서 실행된 최초의 SQL 실행문이어야 한다. 선언문과 C 코드만을 논리적으로 CONNECT 문 앞에 놓을 수 있다. 패스워드를 따로 지정하는 경우는 ORACLE의 유정명과 ORACLE의 패스워드의 양쪽에 대해 호스트 변수를 사용해야 한다.

 양쪽의 호스트 변수를 고정길이 문자열 또는 가변길이 문자열 중의 하나로 선언해야 한다.

 CONNECT 문을 수행하기 전에 양쪽의 호스트 변수를 초기화켜 놓아야 한다.

 CONNECT는 프로그램의 최초의 실행문이지만 논리적인 작업단위의 시작은 아니다.

 

 

2.2 어플리케이션 본체

 

어플리케이션 본체에는 ORACLE 데이터베이스 내에 보존된 데이터를 쿼리하고 조작하기 위한 SQL 문이 들어 있다. 이러한 문은 데이터 조작문이라고 한다. 또한 어플리케이션 본체에는 데이터 정의문이 포함되며 이것은 테이블, 뷰, 인덱스등의 데이터 구조를 작성하거나 정의하기 위해 사용한다.

 ~DECLARE STATEMENT 문

 ~DECLARE DATABASE 문

 ~EXEC ORACLE 옵션

 

 

2.3 Pro*C 예제 프로그램

/* 예제 #1 */
ORACLE의 로그온과 로그오프

#include 
/***************************************************************
This is sample Pro*C program which will log onto a database as
scott/tiger.
***************************************************************/
EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR uid[20];
    VARCHAR pwd[20];
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE SQLCA;

void main(void)
{
    /* log into ORACLE */
    strcpy(uid.arr, "SCOTT");                       /* copy the user name */
    uid.len = strlen(uid.arr);
    strcpy(pwd.arr, "TIGER");                       /* copy the password */
    pwd.len = strlen(pwd.arr);

    EXEC SQL CONNECT :uid IDENTIFIED BY :pwd;

    printf("Connected to ORACLE user : %s\n", uid.arr);
    EXEC SQL COMMIT WORK RELEASE;            /* log off database */
    exit(0);
}


/* 예제 #2 */
    테이블의 작성

#include 

/***************************************************************
This is is a sample Pro*C program which will create a table.
***************************************************************/
EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR uid[20];
    VARCHAR pwd[20];
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE SQLCA;

void main(void)
{
    /* log into ORACLE */
    strcpy(uid.arr, "SCOTT");                       /* copy the user name */
    uid.len = strlen(uid.arr);
    strcpy(pwd.arr, "TIGER");                       /* copy the password */
    pwd.len = strlen(pwd.arr);
    EXEC SQL CONNECT :uid IDENTIFIED BY :pwd;
    printf("Connected to ORACLE user : %s\n", uid.arr);
    EXEC SQL CREATE TABLE Emp_TEST
        (empno     number
        ,ename     char(15)
        ,job        char(10)
        ,mgr       number
        ,hiredate    date
        ,sal         number
        ,deptno     number);
    printf("Table emp_test created. \n");
    EXEC SQL COMMIT WORK RELEASE;
    exit(0);
}

/* 예제 #3 */
      행을 삽입하기 위한 값의 입력지시

#include 
/***************************************************************
This is is a sample Pro*C program which will insert records
into the EMP table by prompting the user for values to be entered.
***************************************************************/
EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR uid[20];
    VARCHAR pwd[20];
    int empno;
    VARCHAR ename[15];
    VARCHAR job[10];
    float sal;
    int deptno;
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE SQLCA;

void main(void)
{
    int sret;                                   /* return code from scanf */

    /* log into ORACLE */
    strcpy(uid.arr, "SCOTT");                       /* copy the user name */
    uid.len = strlen(uid.arr);
    strcpy(pwd.arr, "TIGER");                       /* copy the password */
    pwd.len = strlen(pwd.arr);

    EXEC SQL CONNECT :uid IDENTIFIED BY :pwd;

    printf("Connected to ORACLE user : %s\n\n\n", uid.arr);
    while(1)
    {
        printf("Enter employee number(or 0 to end) : ");
        sret = scanf("%d", &empno);
        if( sret == EOF !! sret == 0 !! empno == 0 )
            break;                                      /* terminate loop */
        printf("Enter employee name : ");
        scanf("%s", ename.arr);
        ename.len = strlen(ename.arr);                /* set the name size */
        printf("Enter employee's job : ");
        scanf("%s", job.arr);
        job.len = strlen(job.arr);                     /* set the job size */
        printf("Enter employee salary : ");
        scanf("%f", &sal);
        printf("Enter employee deptno : ");
        scanf("%d", &deptno);

        EXEC SQL INSERT INTO EMP
                  (empno
                  ,ename
                  ,job
                  ,sal
                  ,deptno)
        VALUES (:empno
                  ,:ename
                  ,:job
                  ,:sal
                  ,:deptno);
        EXEC SQl COMMIT WORK;
        printf("Employee %s added. \n\n", ename.arr);
    }
    EXEC SQL COMMIT WORK RELEASE;            /* log off database */
    exit(0);
}

/* 예제 #4 */
    배열을 이용한 삽입

#include 
/***************************************************************
This is is a sample Pro*C program which uses the FOR option
by inserting records into the EMP table.
***************************************************************/
EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR uid[20];
    VARCHAR pwd[20];
    int empno[100];
    VARCHAR ename[100][15];
    VARCHAR job[100][10];
    VARCHAR hiredate[100][9];
    float sal[100];
    int deptno[100];
    int loop;
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE SQLCA;

FILE *fp;

void main(void)
{
    int i;
    int fsret;

    /* log into ORACLE */
    strcpy(uid.arr, "SCOTT");                        /* copy the user name */
    uid.len = strlen(uid.arr);
    strcpy(pwd.arr, "TIGER");                        /* copy the password */
    pwd.len = strlen(pwd.arr);
    EXEC SQL WHENEVER SQLERROR GOTO errrpt;
    EXEC SQL CONNECT :uid IDENTIFIED BY :pwd;
    printf("Connected to ORACLE user : %s\n\n\n", uid.arr);
    if((fp = fopen("test.dat", "r")) == NULL)
    {
        printf("Error opening file test.dat \n");
        exit(1);
    }
    while(1)
    {
        for(i = 0; i < 100 ; i++)
        {
            fsret = fscanf(fp, "%d %s %s %s %f %d",
                        &empno[i ], ename[i ].arr, job[i ].arr, hiredate[i ].arr,
                        &sal[i ], &deptno[i ]);
            if(fsret == EOF)
                break;
            if(fsret == 0)
            {
                printf("Incompatible field on the line. \n");
                exit(1);
            }
            ename[i ].len = strlen(ename[i ].arr);
            job[i ].len = strlen(job[i ].arr);
            hiredate[i ].len = strlen(hiredate[i ].arr);
        }
        loop = i;
        EXEC SQL FOR :loop
            INSERT INTO EMP(empno, ename, job, hiredate, sal, deptno)
            VALUES(:empno, :ename, :job, :hiredate, :sal, :deptno);
        EXEC SQL COMMIT WORK;
        printf("%d rows inserted. \n", sqlca.sqlerrd[2]);
        if(loop < 100)
            break;
    }
    printf("File test.dat loaded. \n");
    EXEC SQL WHENEVER SQLERROR CONTINUE;
    EXEC SQL COMMIT work RELEASE;
    exit(0);

    errrpt:
        printf("\n %70s \n", sqlca.sqlerrm.sqlerrmc);
        EXEC SQL ROLLBACK WORK RELEASE;
        exit(1);
}

   /* 예제 #5 */
         갱신에 사용하기 위한 값의 입력지시

#include 

/***************************************************************
This is is a sample Pro*C program which will prompt the user
for an employee name and will display thr current sal and comm
fields for that employee.
***************************************************************/
EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR uid[20];
    VARCHAR pwd[20];
    int empno[10];
    float sal, comm;
    short sali, commi;
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE SQLCA;

void main(void)
{
    int sret;

    /* log into ORACLE */
    strcpy(uid.arr, "SCOTT");                       /* copy the user name */
    uid.len = strlen(uid.arr);
    strcpy(pwd.arr, "TIGER");                       /* copy the password */
    pwd.len = strlen(pwd.arr);

    EXEC SQL WHENEVER SQLERROR STOP;
    EXEC SQL WHENEVER NOT FOUND STOP;
    EXEC SQL CONNECT :uid IDENTIFIED BY :pwd;

    printf("Connected to ORACLE user : %s\n", uid.arr);
    printf("Enter employee name to update : ");
    scanf("%s", ename.arr);
    ename.len = strlen(ename.arr);

    EXEC SQL SELECT SAL, COMM
                  INTO  :sal, :comm
                  FROM EMP
                 WHERE ENAME = :ename;

    printf("Employee : %s   sal : %6.2f   comm : %6.2f \n", ename.arr, sal,
            comm);
    printf("Enter new salary : ");
    sret = scanf("%f", &sal);
    sali = 0;
    if(sret == EOF !! sret == 0) sali = 0;
    printf("Enter new commision : ");
    sret = scanf("%f", &comm);
    commi = 0;
    if(sret == EOF !! sret == 0) commi = -1;

    EXEC SQL UPDATE EMP 
                SET     SAL = :sal:sali,
                         COMM = :comm:commi
                WHERE ENAME = :ename;

    printf("Employee %s updateed. \n", ename.arr);
    EXEC SQL COMMIT WORK RELEASE;
    exit(0);
}


   /* 예제 #6 */
       배열을 이용한 갱신


#include 

/***************************************************************
This is is a sample Pro*C program which updates using host
variable arrays. The arrays will be loaded with values
from operator input.
***************************************************************/
EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR uid[20];
    VARCHAR pwd[20];
    int empno[100];
    float sal[100];
    int loop;
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE SQLCA;

void main(void)
{
    int i, sret;

    /* log into ORACLE */
    strcpy(uid.arr, "SCOTT");                       /* copy the user name */
    uid.len = strlen(uid.arr);
    strcpy(pwd.arr, "TIGER");                       /* copy the password */
    pwd.len = strlen(pwd.arr);

    EXEC SQL WHENEVER SQLERROR GOTO errrpt;
    EXEC SQL CONNECT :uid IDENTIFIED BY :pwd;

    printf("Connected to ORACLE user : %s\n", uid.arr);

    while(1)
    {
        for(i = 0; i < 100; i++)
        {
            printf("Enter employee number (or 0 to end loop) : ");
            sret = scanf("%d", &empno[i ]);
            if(sret == EOF !! sret == 0 !! empno[i ] == 0) break;
            printf("Enter updated salary : ");
            sret = scanf("%f", &sal[i ]);
            if(sret == EOF !! sret == 0)
            {
                printf("Error in entry; terminating at this empno. \n");
                break;
            }
        }
        if(i == 0) break;
        loop = i;
        EXEC SQL FOR :loop
            UPDATE EMP SET SAL = :sal
            WHERE EMPNO = :empno;
        EXEC SQL COMMIT WORK;
        printf("%d rows updated. \n", sqlca.sqlerrd[2]);
    }
    printf("Update program complete. \n");
    EXEC SQL WHENEVER SQLERROR CONTINUE;
    EXEC SQL COMMIT WORK RELEASE;
    exit(0);

errrpt:
    printf("\n %70s \n", sqlca.sqlerrm.sqlerrmc);
    EXEC SQL ROLLBACK WORK RELEASE;
    exit(1);
}

/* 예제 #7 */
    배열을 이용한 선택

#include 

/***************************************************************
This is is a sample Pro*C program which selects using host
variable arrays.
***************************************************************/
EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR uid[20];
    VARCHAR pwd[20];
    int empno[100];
    VARCHAR ename[100][15];
    float sal[100];
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE SQLCA;

void main(void)
{
    long num_ret;

    /* log into ORACLE */
    strcpy(uid.arr, "SCOTT");                       /* copy the user name */
    uid.len = strlen(uid.arr);
    strcpy(pwd.arr, "TIGER");                       /* copy the password */
    pwd.len = strlen(pwd.arr);

    EXEC SQL WHENEVER SQLERROR GOTO errrpt;
    EXEC SQL CONNECT :uid IDENTIFIED BY :pwd;

    printf("Connected to ORACLE user : %s\n", uid.arr);

     EXEC SQL DECLARE C1 CURSOR FOR
        SELECT  EMPNO, ENAME, SAL
          FROM   EMP;
    EXEC SQL OPEN C1;
    EXEC SQL WHENEVER NOT FOUND GOTO endloop;
    num_ret = 0;
    while(1)
    {
        EXEC SQL FETCH C1 INTO : empno, :ename, :sal;
        print_rows(sqlca.sqlerrd[2] - num_ret);
        num_ret = sqlca.sqlerrd[2];
    }
endloop:
    if(sqlca.sqlerrd[2] - num_ret > 0)
        print_rows(sqlca.sqlerrd[2] - num_ret);
    printf("\n\nProgram complete. \n");
    EXEC SQL WHENEVER SQLERROR CONTINUE;
    EXEC SQL COMMIT WORK RELEASE;
    exit(0);
errrpt:
    printf("\n %70s \n", sqlca.sqlerrrm.sqlerrmc);
    EXEC SQL ROLLBACK WORK RELEASE;
    exit(1);
}

int print_rows(long n)
{
    long i;
    printf("\n\nEmployee number\tEmployee Name\tSalary\n");
    printf("\n\n---------------\t-------------\t------\n");
    for(i = 1; i < n; i++)
        printf("%15d\t%13s\t%6.2f\n", empno[i ], ename[i ].arr, sal - i);
    return 0;
}
    

/* 예제 #8 */
기존의 테이블로부터 행의 삭제

#include 

/***************************************************************
This is is a sample Pro*C program which will delete a row
from the emp table by prompting for an employee number.
***************************************************************/
EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR uid[20];
    VARCHAR pwd[20];
    int empno;
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE SQLCA;

void main(void)
{
    /* log into ORACLE */
    strcpy(uid.arr, "SCOTT");                       /* copy the user name */
    uid.len = strlen(uid.arr);
    strcpy(pwd.arr, "TIGER");                       /* copy the password */
    pwd.len = strlen(pwd.arr);

    EXEC SQL WHENEVER SQLERROR STOP;
    EXEC SQL CONNECT :uid IDENTIFIED BY :pwd;
    printf("Connected to ORACLE user : %s\n", uid.arr);
    scanf("%d", &empno);

    EXEC SQL DELETE FROM EMP WHERE EMPNO = :empno;
    EXEC SQL COMMIT WORK RELEASE;
    printf("Employee number %d dropped. \n", empno);
    exit(0);
}

 

3.1 쿼리의 구성

 

Pro*C를 사용해서 작성하는 쿼리에는 다음에 나타낸 구를 지정한 어떠한 SELECT 문도 사용할 수 있다.

 

SELECT

INTO

FROM

WHERE

CONNECT

UNION

INTERSECT

MINUS

GROUP BY

HAVING

ORDER BY

 

3.1.1 입력 호스트 변수

WHERE 구 내의 호스트 변수는 입력 호스트 변수라고 부른다.

 

3.1.2 출력 호스트 변수

INTO 구 내의 호스트 변수는 출력 호스트 변수라고 부른다.

 

3.2 1개의 행 만을 리턴하는 쿼리

 

쿼리가 오직 1개의 행 만을 리턴하는 것을 알고 있는 경우는, SELECT 리스트 내의 항목과 같은 수의 출력 호스트 변수를 지정한 INTO 구를 사용한다.

 

3.3 복수의 행을 리턴하는 쿼리(커서의 사용법)

 

쿼리가 복수의 행을 리턴하는 경우, 혹은 몇 개의 행이 리턴됐는지 모를 경우는, SELECT 문과 함께 커서를 사용해야 한다.

커서는 ORACLE 및 Pro*C가 사용하는 작업 영역이고, 이 속에 쿼리의 결과가 포함된다. 커서는 1개의 SELECT문에 대응하고, 쿼리가 변화할 때마다 반복해서 실행된다. 커서는 선언되어야 하며, 데이터의 처리를 위해서 커서를 사용할 때는 아래의 4개의 커서 커맨드를 사용한다.

 DECLARE CURSOR

 OPEN CURSOR

 FETCH

 CLOSE CURSOR

커서를 "OPEN" 한 후 그 커서를 사용해서, 그것에 대응한 쿼리의 결과로서 얻어진 여러 행을 검색 할 수 있다. 쿼리 기준을 만족한 행은 모두 집합의 형식을 취하고, 이것을 커서의 실효집합이라고 부른다. 쿼리가 종료하면 커서를 "CLOSE" 한다.

 

3.3.1 DECLARE CURSOR 문

DECLARE CURSOR 문에서는 커서를 정의한다.

 

EXEC SQL DECLARE cursor_name CURSOR FOR

SELECT … FROM …

 

이 구문은 실제로 다음과 같이 사용한다.

 

EXEC SQL DECLARE C1 CURSOR FOR

SELECT ename, empno, job, sal

FROM emp

WHERE deptno = :deptno;

 

커서를 참조한는 SQL 문을 사용하기 전에 반드시 이커서에 대응하는 DECLARE CURSOR 문을 실행해야 하며, Pro*C는 선언되지 않은 커서에 대한 참조를 해석할 수 없다.

프로그램 내에는 복수의 커서를 사용할 수 있으며 동일 프로그램 내에서 같은 이름의 커서를 지정해서는 안된다.

 

 

3.3.2 OPEN CURSOR

커서를 OPEN 함으로써 쿼리가 판정되고, 행의 실효집합이 식별된다.

EXEC SQL OPEN cursor_name;

 

커서는 OPEN 상태에서 실효집합 최초의 행 직전에 위치된다. 그러나, 실제로 이 시점에서는 아직 어느 행의 검색도 행하지 않는다.

커서를 일단 OPEN 하면 다시 OPEN 하지 않는한, 이 커서의 입력 호스트 변수는 새로이 체크되지 않는다.

 

3.3.3 실효집합의 행의 검색(FETCH 문)

FETCH 문에서는 실효집합의 행을 읽어 들이고, 결과를 얻을 출력 호스트 변수의 이름을 지정한다.

EXEC SQL FETCH cursor_name INTO :hostvar1, :hostvat2 …;

 

이 구문은 실제로 다음과 같이 사용된다.

EXEC SQL FETCH C1 INTO :pename, :pempno, :pjob, :psal;

 

처음으로 커서를 실행하면, 커서는 실효집합의 이전 위치에서 실효집합의 첫째 행으로 이동하며 이 행이 현재의 행이 된다. 커서는 실효집합의 다음행으로만 진행하며 앞에 검색한 행으로 되돌아 가기 위해서는 커서를 CLOSE 하고 다시 오픈해야 한다.

 

3.3.4 CLOSE CURSOR 문

실효집합 행의 검색을 종료한 후 커서를 CLOSE 함으로써, 커서의 OPEN 상태를 유지하기 위해서 사용된 자원을 해제한다.

EXEC SQL CLOSE cursor_name;

 

CLOSE 한 커서에 대해서는 검색을 행할 수 없다.

 

3.4 예제 프로그램

 

/* 예제 #9 */
   WHERE 구에 의한 쿼리

#include 

/***************************************************************
This is is a sample Pro*C program which will display all the
salesman in the employee table.
***************************************************************/
EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR uid[20];
    VARCHAR pwd[20];
    float sal, comm;
    char ename[11];
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE SQLCA;

void main(void)
{
    /* log into ORACLE */
    strcpy(uid.arr, "SCOTT");                       /* copy the user name */
    uid.len = strlen(uid.arr);
    strcpy(pwd.arr, "TIGER");                       /* copy the password */
    pwd.len = strlen(pwd.arr);

    EXEC SQL WHENEVER SQLERROR STOP;
    EXEC SQL CONNECT :uid IDENTIFIED BY :pwd;
    printf("Connected to ORACLE user : %s\n", uid.arr);

    EXEC SQL DECLARE C1 CURSOR FOR
        SELECT ENAME, SAL, COMM
          FROM EMP
        WHERE JOB = 'SALESMAN';
    EXEC OPEN C1;

    EXEC SQL WHENEVER NOT FOUND STOP;
    printf("SALESMAN NAME\t\tSALARY\t\tCOMMISSION\n\n");
    for( ; ; )
    {
        EXEC SQL FETCH C1 INTO :ename, :sal, :comm;
        printf("%-10s\t\t%6.2f\t\t%6.2f \n", ename, sal, comm);
    }
    EXEC SQL CLOSE C1;
    EXEC SQL WHENEVER SQLERROR CONTINUE;   /* don't trap errors */
    EXEC SQL COMMIT WORK RELEASE;
    exit(0);
}
[Top]
No.
제목
작성자
작성일
조회
9030CASE 의 사용예
정재익
2001-12-25
4248
9029NULLIF및 COALESCE 함수
정재익
2001-12-25
4118
9022Pro*C 란? (2)
정재익
2001-12-25
9082
9021Pro*C 란? (I)
정재익
2001-12-25
8215
9020오라클 8i Admin 한글 교본
정재익
2001-12-25
4939
9004OCP 문제 - ADMIN 파트 (4)
정재익
2001-12-23
7934
9003OCP 문제 - ADMIN 파트 (2)
정재익
2001-12-23
12644
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2023 DSN, All rights reserved.
작업시간: 0.053초, 이곳 서비스는
	PostgreSQL v16.1로 자료를 관리합니다