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 9022 게시물 읽기
 News | Q&A | Columns | Tutorials | Devel | Files | Links
No. 9022
Pro*C 란? (2)
작성자
정재익(advance)
작성일
2001-12-25 12:03
조회수
9,067

ORACLE의 기능에 의하여, 유저의 작업 모두가 실행하면 바로 COMMIT되는 것이 아니다. 다시말해서 ORACLE에서는 COMMIT 을 행하기 전에 모든 트랜잭션이 완료되어 있는지를 유저 자신이 확인하도록 되어 있다.

ORACLE은 BEFORE 이미지 파일을 사용하여, 데이터베이스의 일관성을 보호하고 있다. BEFORE 이미지 파일에는 트랜잭션이 시작하기 전의 상태로 데이터베이스의 블록이 보존된다. 상황에 따라 이들의 블록이 데이터베이스 파일에 다시 기록되어, 트랜잭션에 의해 변경된 부분이 변경 전의 상태로 되돌려 진다. 이 같은 처리는 다음과 같은 경우 발생한다.

  유저에 의한 ROLLBACK WORK
  유저 프로세스 내의 ORACLE로부터의 이상 종료
  프로세스간의 데드록
  시스템 장애(H/W OR S/W)

4.1 COMMIT WORK

 

COMMIT WORK 문은 현재 진행 중인 논리적인 작업단위를 종료하게 하고, 이 작업단위 내에서 행해진 변경을 모두 확정한다.

EXEC SQL COMMIT WORK [RELEASE];

 

RELEASE 옵션 파라미터는 프로그램이 소유하고 있는 자원을 모두 리턴하고, 데이터베이스에서 로그로프한다.

 

4.2 ROLLBACK WORK

 

ROLLBACK WORK 문은 현재 진행 중인 논리적인 작업단위를 종료하게 하고, 이 작업단위에서 행한 변경을 취소한다.

EXEC SQL ROLLBACK WORK [RELEASE];

 

유저는 RELEASE 옵션을 사용해서 최후의 작업단위를 반드시 명시적으로 COMMIT 또는 ROLLBACK해야 한다.

 

5.1 표지 변수에 리턴된 값의 사용

 

어느 호스트 변수에도 임의 선택 변수인 표지 변수를 대응시킬 수 있다. 이 표지 변수를 사용하면 각각의 필드 값이 어떤 경우인지 알 수 있다.

값      의미
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 0    리턴되는 값은 호스트 변수에 보존된다. 이것은 널도 아니고,
      절사도 되지 않는다.
-1   리턴된 값은 널이다. 호스트 변수의 값은 정의되지 않는다.
20   리턴된 값은 절사되어 있다. 호스트 변수의 폭이 충분하지 않다.
      표지 변수에 설정된 값은 절사되기 전의 폭이다

5.2 SQLCA의 구조

 

SQLCA 는 프로그램의 실행에 관한 정보를 교환하기 위해, 모든 Pro*C 프로그램에서 사용한다. SQLCA는 각각의 트랜잭션에 대해서 널 값의 무시여부, 쿼리를 시작하고 나서 데이터의 변경 여부등을 표시하므로, 프로그래머는 각각의 데이터 상태를 확인할 수 있다.

 

5.2.1 SQLCA를 참조하는 타이밍

SQLCA는 각 SQL 실행문의 실행 때마다 갱신된다. 따라서 프로그래머는 각 실행문 뒤에서 SQLCA를 검색해야 한다. 특히 각 DML 문 뒤에서는 SQLCA를 검색할 필요가 있다. 이는 테이블 속의 일부의 행만을 처리한 뒤에 INSERT 및 UPDATE 문이 실패한다면, 유저는 데이터베이스을 어떤 일관성 있는 상태로 회복하기 위해 ROLLBACK WORK 커맨드를 실행해야 하기 때문이다.

WHENEVER 문을 사용하면 이상 상태를 검출하고 그 상태에 따라 적절히 동작을 지정할 수 있다. 다음은 WHENEVER 문의 디폴트 값이다.

EXEC SQL WHENEVER anyerror CONTINUE;

 

5.2.2 SQLCA의 각 요소의 의미

struct sqlca {
      char sqlcaid[8];
      long sqlcabc;
      long sqlcode;
      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   4바이트 2진 정수이고, SQL 문의 실행결과를 나타낸다.
                        0  실행이 정상 종료
                        1403  NOT FOUND
                         음수  프로그램 또는 시스템 장애
     *sqlca.sqlerrm.sqlerrml sqlca.sqlerrm.sqlerrmc의 텍스트의 길이
  *sqlca.sqlerrm.sqlerrmc 가변 길이의 문자열이고, sqlca.sqlcode 내에
                                              표시된 에러번호에 대응하는 에러메세지
  *sqlca.sqlerrd   4바이트 2진 정수 배열 ORACLE RDBMS의 내부상황을 
                               파악하기 위해 사용. sqlca.sqlerrd[2]는 INSERT나 UPDATE
                               처럼 DML 처리에 대해서 몇 개의 행이 처리 됐는지를 나타냄
  *sqlca.sqlwarn   프리컴파일 중에 발생한 여러가지 상황에 대한 경고
        sqlca.sqlwarn[0]  "W"가 설정된 경우 1개 이상의 경고가 설정되어 있음

5.3 WHENEVER 문

  에러를 검출할 때 어떤 처리를 취해야 할 지를 결정한다.
   EXEC SQL WHENEVER [SQLERROR | SQLWARNING | NOT FOUND]
                         [STOP | CONTINUE | GOTO stmt-label];

  SQLERROR      sqlca.sqlcode가 -1인 경우에 설정
  SQLWARNING  sqlca.sqlwarn[0]에 "W"가 설정되어 있는 경우에 설정
  NOT FOUND    sqlca.sqlcode가 1403인 경우에 설정
  STOP             프로그램을 종료시키고 논리적인 작업단위는 ROLLBACK 된다.
  CONTINUE      sqlca의 상태를 무시하고 프로그램을 계속 진행한다.
  GOTO             지정한 라벨이 붙은 문으로 제어를 옮긴다.

 

6. 동적 정의문

 

6.1 동적 정의문의 정의

 

동적 정의문이란, 컴파일시에 정의되지 않는 SQL 문이다. 다시 말해서, 동적 정의문은 각각의 실행 때마다 변경이 가능하고, 실제로 많은 경우에 변경된다.

 

6.2 동적 정의문의 종류

방법 1 : EXECUTE IMMEDIATE 문의 사용
  모든 SQL 문(SELECT 문 제외)을 프리컴파일해서 이것을 실행한다.
  SQL 문은 상수 또는 호스트 변수 중 어느 것이라도 상관없다.
  SQL 문에는 호스트 변수를 포함하지 않는다.

방법 2 : PREPARE 문 및 EXECUTE 문의 사용
  모든 SQL 문(SELECT 문 제외)을 받아들여 이것을 수행한다.
  SQL 문 중에 호스트 변수를 포함할 수 있다.
  
방법 3 : PREPARE 문 및 FETCH 문의 사용
  선택을 행할 수 있다. SQL 문 중에 호스트 변수를 포함할 수 있다.
  이 방법은 PREPARE, DECLARE, OPEN, FETCH의 순서로 행한다.

방법 4 : 바인드 및 정의 기술자의 사용
  1행의 SELECT 및 여러 행의 SELECT를 포함하는 모든 SQL 문을
  사용할 수 있다.

6.3 EXECUTE IMMEDIATE 의 사용

/* 예제 #10 */
#include 
/***************************************************************
This is is a sample Pro*C program which will prompt for a
WHERE clause to be used in an update statement. This is to be
used with EXECUTE IMMEDIATE.
***************************************************************/

EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR uid[20];
    VARCHAR pwd[20];
    char select[132];
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE SQLCA;

void main(void)
{
    char where[80];
    int scode;

    /* 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);

    strcpy(select, "UPDATE EMP SET COMM = 100 WHERE");
    printf("Please enter where clause for the following : \n");
    printf("%s", select);
    scode = scanf("%s", where);
    if(scode == EOF !! scode == 0)
    {
        printf("Invalid entry. \n");
        exit(1);
    }
    strcat(select, where);

    EXEC SQL EXECUTE IMMEDIATE :select;

    printf("%d records updated. \n", sqlca.sqlerrd[2]);
    EXEC SQL WHENEVER SQLERROR CONTINUE;
    EXEC SQL COMMIT WORK RELEASE;
    exit(0);
}

6.4 PREPARE 및 EXECUTE 의 사용

/* 예제 #11 */
#include 
/***************************************************************
This is is a sample Pro*C program which will prompt for a
WHERE clause to be used in an update statement. This is to be
used with PREPARE and EXECUTE.
***************************************************************/
EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR uid[20];
    VARCHAR pwd[20];
    float comm;
    char select[132];
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE SQLCA;

void main(void)
{
    char where[80];
    int scode;

    /* 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);

    strcpy(select, "UPDATE EMP SET COMM = :comm WHERE");
    printf("Please enter where clause for the follwing : \n");
    printf("%s", select);
    scode = scanf("%s", where);
    if(scode == EOF !! scode == 0)
    {
        printf("Invalid entry. \n");
        exit(1);
    }
    strcat(select, where);

    EXEC SQL PREPARE S1 FROM :select;

    printf("Please enter commission : ");
    scanf("%f", &comm);
    EXEC SQL EXECUTE S1 USING :comm;

    printf("%d records updated. \n", sqlca.sqlerrd[2]);
    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);
}        

 

6.5 PREPARE, DECLARE, OPEN, FETCH, CLOSE 의 사용

/* 예제 #12 */
#include 

/***************************************************************
This is is a sample Pro*C program which will prompt for a
WHERE clause to be used in a select statement.
This sample uses PREPARE, DECLARE, OPEN, FETCH, CLOSE
since this may be a multi-row select and world require a cursor.
***************************************************************/
EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR uid[20];
    VARCHAR pwd[20];
    int deptno;
    float sal;
    char select[132];
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE SQLCA;

void main(void)
{
    char where[80];
    int i, scode;

    /* 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);
    strcpy(select, "SELECT ENAME, SAL FROM EMP ");
    printf("Please enter where clause for the following : \n");
    printf("%s", select);
    scode = scanf("%s", where);
    if(scode == EOF !! scode == 0)
    {
        printf("Invalid entry. \n");
        exit(1);
    }
    strcat(select, where);

    EXEC SQL PREPARE S1 FROM :select;
    EXEC SQL DECLARE C1 CURSOR FOR S1;
    EXEC SQL OPEN C1;
    printf("Employee       \tSalary       \n");
    printf("--------------\t-----------\n");

    EXEC SQL WHENEVER NOT FOUND GOTO endloop;
    for(i = 0; ; i++)
    {
        EXEC SQL FETCH C1 INTO :ename, :sal;
      printf("%10s\t%6.2f\n", ename, sal);
    }

endloop:
    printf("\n\n%d records selected.\n", i);
    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.1 STORED PROCEDURE 의 사용

 

/* calldemo.sql */
rem 
Rem    calldemo.sql - 
Rem    DESCRIPTION
Rem    
Rem    RETURNS
Rem 

CREATE OR REPLACE PACKAGE calldemo AS
   TYPE name_array IS TABLE OF emp.ename%type
       INDEX BY BINARY_INTEGER;
   TYPE job_array IS TABLE OF emp.job%type
       INDEX BY BINARY_INTEGER;
   TYPE sal_array IS TABLE OF emp.sal%type
       INDEX BY BINARY_INTEGER;

   PROCEDURE get_employees(
     dept_number IN     number,    -- department to query
     batch_size  IN     INTEGER,   -- rows at a time
     found       IN OUT INTEGER,   -- rows actually returned
     done_fetch  OUT    INTEGER,   -- all done flag
     emp_name    OUT    name_array,
     job         OUT    job_array,
     sal         OUT    sal_array);
END calldemo;
/

CREATE OR REPLACE PACKAGE BODY calldemo AS
   CURSOR get_emp (dept_number IN number) IS
       SELECT ename, job, sal FROM emp
           WHERE deptno = dept_number;

   PROCEDURE get_employees(
     dept_number IN     number,
     batch_size  IN     INTEGER,
     found       IN OUT INTEGER,
     done_fetch  OUT    INTEGER,
     emp_name    OUT    name_array,
     job         OUT    job_array,
     sal         OUT    sal_array) IS

   BEGIN
       IF NOT get_emp%ISOPEN THEN      -- open the cursor if
           OPEN get_emp(dept_number);  -- not already open
       END IF;
       done_fetch := 0;  -- set the done flag FALSE
       found := 0;
       FOR i IN 1..batch_size LOOP
           FETCH get_emp INTO emp_name(i), job(i), sal(i);
           IF get_emp%NOTFOUND THEN    -- if no row was found
               CLOSE get_emp;
               done_fetch := 1;   -- indicate all done
               EXIT;
           ELSE
               found := found + 1;  -- count row
           END IF;
       END LOOP;
   END;
END;
/


 /* 예제 #13 */

#include 
#include 
/***************************************************************
This program connects to ORACLE using the SCOTT/TIGER account.  
The program declares several host arrays, then calls a PL/SQL 
stored procedure (GET_EMPLOYEES in the CALLDEMO package) 
that fills the table OUT parameters. The PL/SQL procedure returns 
up to ASIZE values.
****************************************************************/
EXEC SQL INCLUDE sqlca.h;

typedef char asciz[20];
typedef char vc2_arr[11];

EXEC SQL BEGIN DECLARE SECTION;
    /* User-defined type for null-terminated strings */
    EXEC SQL TYPE asciz IS STRING(20) REFERENCE;
    /* User-defined type for a VARCHAR array element. */
    EXEC SQL TYPE vc2_arr IS VARCHAR2(11) REFERENCE;
    asciz     username;
    asciz     password;
    int       dept_no;                  /* which department to query? */
    vc2_arr   emp_name[10];            /* array of returned names */
    vc2_arr   job[10];
    float     salary[10];
    int       done_flag;
    int       array_size;
    int       num_ret;                 /* number of rows returned */
EXEC SQL END DECLARE SECTION;

long      SQLCODE;

void print_rows();            /* produces program output      */
void sql_error();             /* handles unrecoverable errors */

main()
{
    int   i;
    char  temp_buf[32];

    /* Connect to ORACLE. */
    EXEC SQL WHENEVER SQLERROR DO sql_error();
    strcpy(username, "scott");
    strcpy(password, "tiger");
    EXEC SQL CONNECT :username IDENTIFIED BY :password;
    printf("\nConnected to ORACLE as user: %s\n\n", username);

    printf("Enter department number: ");
    gets(temp_buf);
    dept_no = atoi(temp_buf);

    /* Print column headers. */
    printf("\n\n");
    printf("%-10.10s%-10.10s%s\n", "Employee", "Job", "Salary");
    printf("%-10.10s%-10.10s%s\n", "--------", "---", "------");

    /* Set the array size. */
    array_size = 10;
    done_flag = 0;
    num_ret = 0;
    /*  Array fetch loop.
     *  The loop continues until the OUT parameter done_flag is set.
     *  Pass in the department number, and the array size--
     *  get names, jobs, and salaries back. */
     for ( ; ; )
    {
        EXEC SQL EXECUTE 
            BEGIN calldemo.get_employees
                (:dept_no, :array_size, :num_ret, :done_flag,
                 :emp_name, :job, :salary);
            END;
        END-EXEC;

        print_rows(num_ret);
        if(done_flag) break;
    }
    /* Disconnect from the database. */
    EXEC SQL COMMIT WORK RELEASE;
    exit(0);
}

void print_rows(int n)
{
    int i;

    if (n == 0)
    {
        printf("No rows retrieved.\n");
        return;
    }
    for (i = 0; i < n; i++)
        printf("%10.10s%10.10s%6.2f\n", emp_name[i ], job[i ], salary[i ]);
}

 /* Handle errors. Exit on any error. */
void sql_error()
{
    char msg[512];
    int buf_len, msg_len;

    EXEC SQL WHENEVER SQLERROR CONTINUE;

    buf_len = sizeof(msg);
    sqlglm(msg, &buf_len, &msg_len);

    printf("\nORACLE error detected:");
    printf("\n%.*s \n", msg_len, msg);

    EXEC SQL ROLLBACK WORK RELEASE;
    exit(1);
}

 

8. Pro*C/C++의 사용

 

8.1 디렉토리 또는 경로의 설정

OS에서 디렉토리 또는 경로를 사용하고 있는 경우 경로 또는 디렉토리의 이름이 장치의 지정과 함께 올바른 지를 확인해야 한다.

 

8.2 커맨드 구문

 

일반적인 커맨드 구문은 다음과 같다.

PCC INAME = filename {option=value (option=value …)}

 

8.2.1 필수 인수

필수 인수는 "INAME = 파일명" 하나뿐이다. 파일의 확장자나 파일타입을 지정하지 않는 경우 "HOST = 언어"를 인수로서 지정해야 한다.

Pro*C에서 입력파일 및 출력파일에 대한 파일타입 및 확장자의 디폴트값은 다음과 같다.

OS          입력파일타입 또는 확장자      출력파일타입 또는 확장자
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
VAX/VMS               .pc                                  .c
IBM/VM/CMS         csql                                c
UNIX                      .pc                                  .c

 

8.2.2. Pro*C의 실행시 옵션

  실행시에는 복수의 옵션을 사용할 수 있다.
OPTION = value

 · AREASIZE
 · ASACC
 · ERRORS
 · HOLD_CURSOR/RELEASE_CURSOR
 · HOST
 · INCLUDE
 · IRECLEN
 · LNAME
 · LRECLEN
 · LTYPE
 · MAXLITERAL
 · MAXOPENCURSOR
 · ONAME
 · ORACA
 · ORECLEN
 · PAGELEN
 · REBIND
 · SELECT_ERROR
 · USERID
 · XREF

[Top]
No.
제목
작성자
작성일
조회
9031오라클 Performance Tuning Scripts
정재익
2001-12-25
4212
9030CASE 의 사용예
정재익
2001-12-25
4235
9029NULLIF및 COALESCE 함수
정재익
2001-12-25
4104
9022Pro*C 란? (2)
정재익
2001-12-25
9067
9021Pro*C 란? (I)
정재익
2001-12-25
8201
9020오라클 8i Admin 한글 교본
정재익
2001-12-25
4928
9004OCP 문제 - ADMIN 파트 (4)
정재익
2001-12-23
7923
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2023 DSN, All rights reserved.
작업시간: 0.051초, 이곳 서비스는
	PostgreSQL v16.1로 자료를 관리합니다