21
Oracle Embedded SQL Pro*C : Chap 7 작 : 작작작 작 : [email protected] 작 : 1.15 Copyright by SunYoung Kim

Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : [email protected] 버 전 : 1.15 Copyright by SunYoung Kim

Embed Size (px)

Citation preview

Page 1: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Oracle Embedded SQLOracle Embedded SQL

Pro*C : Chap 7Pro*C : Chap 7

작 성 자 : 김선영

메 일 : [email protected]

버 전 : 1.15

Copyright by SunYoung Kim

Page 2: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Copyright by SunYoung Kim <sunyzero (at) gmail (dot) com>

PrefacePreface

Oracle 은 Oracle 의 등록상표입니다 .

Pro*C 는 Oracle 의 제품입니다 .

예제는 지면 제약상 한줄에 여러라인이 코딩될 수 있습니다 .

본 자료에 대한 질문사항은 연락처를 참고해주시기 바랍니다 .

E-mail address

sunyzero (at) gmail (dot) com

sunyzero (at) empal (dot) com

Page 3: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Copyright by SunYoung Kim <sunyzero (at) gmail (dot) com>

Pro*C Dyanamic SQLPro*C Dyanamic SQL 특징

Static SQL 문과 달리 작성시에는 statement, variable type, # of variable 의 개수를 알 수 없는 경우에 사용함 .

반복적인 구문의 경우 , cache 로 올려 작업할 수 있게 함 .

» cache 에 올려지게 되면 SQL 구문을 해석하는 시간이 생략됨

시행 순서

» SQL 문 작성

» PREPARE : 구문을 해석해서 cache 로 올림

» EXECUTE : cache 에 올린 구문에 데이터를 맵핑하여 실행함

Page 4: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Copyright by SunYoung Kim <sunyzero (at) gmail (dot) com>

Pro*C Dyanamic SQL ( 계속 )Pro*C Dyanamic SQL ( 계속 ) select list item

SELECT 구문에서 지정한 출력 컬럼 리스트

» 아래의 경우는 NAME, AGE 가 해당함

» e.g. SELECT NAME, AGE FROM ...

placeholder

실제 SQL 구문이 실행될때 다른 호스트변수에 의해서 대체됨

입력 매개변수 (parameter) 로 사용됨

이름은 특별히 규칙이 없음 . 아래의 경우 v1, v2 가 해당함 .

» e.g. SELECT NAME, AGE FROM ... WHERE NAME like :v1 AGE > :v2

Page 5: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Copyright by SunYoung Kim <sunyzero (at) gmail (dot) com>

MethodsMethods Dynamic SQL 문은 4 가지의 method 를 지원함

Method 1 : SELECT 구문이 아닌 1 회성 실행을 하는 경우

» c.f.) cache 에 올라가는 작업이 아님

Method 2 : SELECT 구문이 아닌 반복적인 실행을 요하는 경우

Method 3 : 정적인 SELECT 구문의 반복적인 실행을 요하는 경우

Method 4 : 동적인 SELECT 구문의 반복적인 실행을 요하는 경우

Page 6: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Copyright by SunYoung Kim <sunyzero (at) gmail (dot) com>

Method 1Method 1 Method 1

SELECT 구문이 아닌 1 회성 실행을 하는 경우

EXECUTE IMMEDIATE 명령으로 즉시 실행하도록 함

» EXECUTE IMMEDIATE < host var. with SQL statement >

while (1) {

printf("input table name to remove (^d to exit): ");

fflush(stdout);

memset(c_str, 0, sizeof(c_str));

if (fgets(c_str, sizeof(c_str), stdin) == NULL) {

exit(EXIT_SUCCESS);

}

sprintf(sqlstmt, "DROP TABLE %s CASCADE CONSTRAINT", c_str);

EXEC SQL EXECUTE IMMEDIATE :sqlstmt;

}

while (1) {

printf("input table name to remove (^d to exit): ");

fflush(stdout);

memset(c_str, 0, sizeof(c_str));

if (fgets(c_str, sizeof(c_str), stdin) == NULL) {

exit(EXIT_SUCCESS);

}

sprintf(sqlstmt, "DROP TABLE %s CASCADE CONSTRAINT", c_str);

EXEC SQL EXECUTE IMMEDIATE :sqlstmt;

}

Page 7: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Copyright by SunYoung Kim <sunyzero (at) gmail (dot) com>

Method 2Method 2 Method 2

SELECT 구문이 아닌 반복적인 실행을 요하는 경우

» e.g.) INSERT, UPDATE 구문

select-item-list 와 placeholder 를 미리 지정함

PREPARE, EXECUTE 명령을 사용

» PREPARE statement FROM < SQL literal | host_var >;

» EXECUTE statment [ USING <input_host_var>;

Page 8: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Copyright by SunYoung Kim <sunyzero (at) gmail (dot) com>

Method 2 (con't)Method 2 (con't) "pr7_method2.pc"

text file 로부터 raw data 를 REGEX 로 추출하여 table 에 insert 하는 예제

#include "myproc.h"

#define MAX_EXPR_SUB_MATCH 10

#define DEF_FILENAME "regdata.txt"

#define REGEX_STR "^([a-zA-Z ]+)[|,]([0-9 ]+)[|,]([a-zA-Z ]+)[|,]+([a-zA-Z ]+)"

#include "sqlca.h"

#include "oraca.h"

EXEC ORACLE OPTION (ORACA=YES);

#define DB_USER "scott"

#define DB_PASS "xkdlrj"

typedef struct my_record {

unsigned short sno;

char name[30+1];

unsigned short gender;

unsigned short age;

char locale[20+1];

} MY_RECORD;

#include "myproc.h"

#define MAX_EXPR_SUB_MATCH 10

#define DEF_FILENAME "regdata.txt"

#define REGEX_STR "^([a-zA-Z ]+)[|,]([0-9 ]+)[|,]([a-zA-Z ]+)[|,]+([a-zA-Z ]+)"

#include "sqlca.h"

#include "oraca.h"

EXEC ORACLE OPTION (ORACA=YES);

#define DB_USER "scott"

#define DB_PASS "xkdlrj"

typedef struct my_record {

unsigned short sno;

char name[30+1];

unsigned short gender;

unsigned short age;

char locale[20+1];

} MY_RECORD;

Page 9: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Copyright by SunYoung Kim <sunyzero (at) gmail (dot) com>

Method 2 (con't)Method 2 (con't)

int prep_stmt(void);

int set_record(MY_RECORD *, const char *, const regmatch_t *);

int insert_rec(const MY_RECORD *s);

int main(int argc, char **argv) {

char *p_filename;

regex_t re_expr; /* posix regex patern buffer */

regmatch_t rm_matchtab[MAX_EXPR_SUB_MATCH]; /* pattern matching table */

int i, ret;

FILE *fp;

char errbuf[0xff], buf[0xff];

MY_RECORD a_rec;

if (argc != 2) {

printf("Using default filename!\n");

p_filename = DEF_FILENAME;

} else {

p_filename = strdup(argv[1]);

}

int prep_stmt(void);

int set_record(MY_RECORD *, const char *, const regmatch_t *);

int insert_rec(const MY_RECORD *s);

int main(int argc, char **argv) {

char *p_filename;

regex_t re_expr; /* posix regex patern buffer */

regmatch_t rm_matchtab[MAX_EXPR_SUB_MATCH]; /* pattern matching table */

int i, ret;

FILE *fp;

char errbuf[0xff], buf[0xff];

MY_RECORD a_rec;

if (argc != 2) {

printf("Using default filename!\n");

p_filename = DEF_FILENAME;

} else {

p_filename = strdup(argv[1]);

}

Page 10: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Copyright by SunYoung Kim <sunyzero (at) gmail (dot) com>

Method 2 (con't)Method 2 (con't)

if ((ret = regcomp(&re_expr, REGEX_STR, REG_EXTENDED|REG_NEWLINE))) {

regerror(ret, &re_expr, errbuf, sizeof(errbuf));

printf("Error regcomp() : %s\n", errbuf);

exit(EXIT_FAILURE);

}

printf("regcomp : %s\n", REGEX_STR);

/* practice2: remove WEHNEVER statement */

EXEC SQL WHENEVER SQLERROR DO branch_ora_err();

if (get_dbconn(DB_USER, DB_PASS, NULL)) {

fprintf(stderr, "Fail: get_dbconn\n");

exit(EXIT_FAILURE);

}

oraca.orastxtf = ORASTFERR; /* save SQL literal at error */

prep_stmt();

/* 파일 열기 부분은 생략됨 */

if ((ret = regcomp(&re_expr, REGEX_STR, REG_EXTENDED|REG_NEWLINE))) {

regerror(ret, &re_expr, errbuf, sizeof(errbuf));

printf("Error regcomp() : %s\n", errbuf);

exit(EXIT_FAILURE);

}

printf("regcomp : %s\n", REGEX_STR);

/* practice2: remove WEHNEVER statement */

EXEC SQL WHENEVER SQLERROR DO branch_ora_err();

if (get_dbconn(DB_USER, DB_PASS, NULL)) {

fprintf(stderr, "Fail: get_dbconn\n");

exit(EXIT_FAILURE);

}

oraca.orastxtf = ORASTFERR; /* save SQL literal at error */

prep_stmt();

/* 파일 열기 부분은 생략됨 */

Page 11: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Copyright by SunYoung Kim <sunyzero (at) gmail (dot) com>

Method 2 (con't)Method 2 (con't)

while (!feof(fp)) { /* Loop: extract raw data from file */

if (fgets(buf, sizeof(buf), fp) == NULL) break;

memset(rm_matchtab, 0x00, sizeof(rm_matchtab));

if (regexec(&re_expr, buf, MAX_EXPR_SUB_MATCH, rm_matchtab, 0)) {

printf("fail to match: (%.30s ...)\n", buf);

} else {

printf("* All Match offset:(%1$d->%2$d), len(%3$d) : %4$.*3$s\n",

rm_matchtab[0].rm_so, rm_matchtab[0].rm_eo,

rm_matchtab[0].rm_eo - rm_matchtab[0].rm_so,

&buf[rm_matchtab[0].rm_so]);

for (i=1; i<MAX_EXPR_SUB_MATCH; i++) {

if (rm_matchtab[i].rm_so == -1) break;

printf("\tSubmatch[%d] offset:(%2$d->%3$d), len(%4$d):%5$.*4$s\n",i,

rm_matchtab[i].rm_so, rm_matchtab[i].rm_eo,

rm_matchtab[i].rm_eo - rm_matchtab[i].rm_so,

&buf[rm_matchtab[i].rm_so]);

}

while (!feof(fp)) { /* Loop: extract raw data from file */

if (fgets(buf, sizeof(buf), fp) == NULL) break;

memset(rm_matchtab, 0x00, sizeof(rm_matchtab));

if (regexec(&re_expr, buf, MAX_EXPR_SUB_MATCH, rm_matchtab, 0)) {

printf("fail to match: (%.30s ...)\n", buf);

} else {

printf("* All Match offset:(%1$d->%2$d), len(%3$d) : %4$.*3$s\n",

rm_matchtab[0].rm_so, rm_matchtab[0].rm_eo,

rm_matchtab[0].rm_eo - rm_matchtab[0].rm_so,

&buf[rm_matchtab[0].rm_so]);

for (i=1; i<MAX_EXPR_SUB_MATCH; i++) {

if (rm_matchtab[i].rm_so == -1) break;

printf("\tSubmatch[%d] offset:(%2$d->%3$d), len(%4$d):%5$.*4$s\n",i,

rm_matchtab[i].rm_so, rm_matchtab[i].rm_eo,

rm_matchtab[i].rm_eo - rm_matchtab[i].rm_so,

&buf[rm_matchtab[i].rm_so]);

}

Page 12: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Copyright by SunYoung Kim <sunyzero (at) gmail (dot) com>

Method 2 (con't)Method 2 (con't)

if (set_record(&a_rec, buf, rm_matchtab)) {/* make tuple */

fprintf(stderr, "[%s:%d] FAIL: set_record()\n", __FILE__, __LINE__);

break;

}

if (insert_rec(&a_rec)) { /* insert to table */

fprintf(stderr, "[%s:%d] FAIL: insert_rec()\n", __FILE__, __LINE__);

break;

}

if (commit_work()) { /* commit work */

fprintf(stderr, "[%s:%d] FAIL: commit_work()\n", __FILE__, __LINE__);

exit(EXIT_FAILURE);

}

}

}

regfree(&re_expr); /* free memory for REGEX pattern buffer */

if (close_dbconn(1)) {

fprintf(stderr, "[%s:%d] FAIL: close_dbconn()\n", __FILE__, __LINE__);

}

return 0;

}

if (set_record(&a_rec, buf, rm_matchtab)) {/* make tuple */

fprintf(stderr, "[%s:%d] FAIL: set_record()\n", __FILE__, __LINE__);

break;

}

if (insert_rec(&a_rec)) { /* insert to table */

fprintf(stderr, "[%s:%d] FAIL: insert_rec()\n", __FILE__, __LINE__);

break;

}

if (commit_work()) { /* commit work */

fprintf(stderr, "[%s:%d] FAIL: commit_work()\n", __FILE__, __LINE__);

exit(EXIT_FAILURE);

}

}

}

regfree(&re_expr); /* free memory for REGEX pattern buffer */

if (close_dbconn(1)) {

fprintf(stderr, "[%s:%d] FAIL: close_dbconn()\n", __FILE__, __LINE__);

}

return 0;

}

Page 13: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Copyright by SunYoung Kim <sunyzero (at) gmail (dot) com>

Method 2 (con't)Method 2 (con't)

int prep_stmt(void)

{

EXEC SQL PREPARE S_EMPLIST FROM INSERT INTO EMPLIST VALUES

(SEQ_EMPLIST.NEXTVAL, :v1, :v2, :v3, :v4);

return 0;

}

int insert_rec(const MY_RECORD *s) {

EXEC SQL EXECUTE S_EMPLIST USING

:s->name, :s->gender, :s->age, :s->locale;

return SQLCODE;

}

#define COPY_RMTAB(dest, src, matchtab) memcpy(dest, &src[matchtab.rm_so], \

matchtab.rm_eo - matchtab.rm_so); \

dest[matchtab.rm_eo - matchtab.rm_so] = 0x0

int prep_stmt(void)

{

EXEC SQL PREPARE S_EMPLIST FROM INSERT INTO EMPLIST VALUES

(SEQ_EMPLIST.NEXTVAL, :v1, :v2, :v3, :v4);

return 0;

}

int insert_rec(const MY_RECORD *s) {

EXEC SQL EXECUTE S_EMPLIST USING

:s->name, :s->gender, :s->age, :s->locale;

return SQLCODE;

}

#define COPY_RMTAB(dest, src, matchtab) memcpy(dest, &src[matchtab.rm_so], \

matchtab.rm_eo - matchtab.rm_so); \

dest[matchtab.rm_eo - matchtab.rm_so] = 0x0

Page 14: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Copyright by SunYoung Kim <sunyzero (at) gmail (dot) com>

Method 2 (con't)Method 2 (con't)

int set_record(MY_RECORD *d, const char *sbuf, const regmatch_t *rmtab)

{

char buf[40];

/* name : 1st field => rmtab[1] */

COPY_RMTAB(d->name, sbuf, rmtab[1]);

/* gender: 3rd field => rmtab[3] */

COPY_RMTAB(buf, sbuf, rmtab[3]);

if (strncmp(buf, "Male", 4) == 0) { /* has logical error! */

d->gender = 1;

} else {

d->gender = 2; /* always '2'. what's problem? */

}

/* age : 2nd field => rmtab[2] */

COPY_RMTAB(buf, sbuf, rmtab[2]);

d->age = atoi(buf);

/* locale: 4th field => rmtab[4] */

COPY_RMTAB(d->locale, sbuf, rmtab[4]);

return 0;

}

int set_record(MY_RECORD *d, const char *sbuf, const regmatch_t *rmtab)

{

char buf[40];

/* name : 1st field => rmtab[1] */

COPY_RMTAB(d->name, sbuf, rmtab[1]);

/* gender: 3rd field => rmtab[3] */

COPY_RMTAB(buf, sbuf, rmtab[3]);

if (strncmp(buf, "Male", 4) == 0) { /* has logical error! */

d->gender = 1;

} else {

d->gender = 2; /* always '2'. what's problem? */

}

/* age : 2nd field => rmtab[2] */

COPY_RMTAB(buf, sbuf, rmtab[2]);

d->age = atoi(buf);

/* locale: 4th field => rmtab[4] */

COPY_RMTAB(d->locale, sbuf, rmtab[4]);

return 0;

}

Page 15: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Copyright by SunYoung Kim <sunyzero (at) gmail (dot) com>

Method 3Method 3 Method 3

select-list-item 과 input host variable 의 수를 지정하여 SELECT 구문을 실행

CURSOR 를 이용함

PREPARE, DECLARE CURSOR, OPEN CURSOR, FETCH, CLOSE CURSOR

» PREPARE statement FROM < SQL literal | host_var >;

» DECLARE <cursor_identifier> CURSOR FOR <sql | statememt>;

» OPEN <cursor_identifier> USING host_variable_list;

» FETCH <cursor_identifier> INTO <host_var> [ INDICATOR <ind_var> ];

» CLOSE <cursor_identifier>;

Page 16: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Copyright by SunYoung Kim <sunyzero (at) gmail (dot) com>

Method 3 (con't)Method 3 (con't) proc precompiler option

prefetch # : Cursor 를 open 했을때 prefetch 할 row 의 개수

» array 사용시 array 사용하는 크기와 같은 것이 좋음

sqlca.sqlerrd[2]

cumulative fetched row 가 기록됨

array-fetch 를 할때 중요하게 사용됨

Page 17: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Copyright by SunYoung Kim <sunyzero (at) gmail (dot) com>

Method 3 (con't)Method 3 (con't) "pr6_method3.pc"

#define MAX_ITERATION 50

struct e_member {

int idnum; char name[21]; short age; char desc[513]; int uniqid;

};

typedef struct e_member E_MEMBER;

void pr_em(const E_MEMBER *s); /* pr_em은 생략되었으니 앞의 예제를 참고합시다 */

int main(int argc, char *argv[])

{

int i, i_age; E_MEMBER p_em; char c_str[50], sqlstmt[1024];

if (argc != 3) {

printf("Usage : %s <username> <passwd>\n",argv[0]); return EXIT_SUCCESS;

}

/* get database connection */

if (get_dbconn(argv[1], argv[2], NULL)) {

return EXIT_FAILURE;

}

EXEC SQL WHENEVER SQLERROR DO branch_ora_err();

#define MAX_ITERATION 50

struct e_member {

int idnum; char name[21]; short age; char desc[513]; int uniqid;

};

typedef struct e_member E_MEMBER;

void pr_em(const E_MEMBER *s); /* pr_em은 생략되었으니 앞의 예제를 참고합시다 */

int main(int argc, char *argv[])

{

int i, i_age; E_MEMBER p_em; char c_str[50], sqlstmt[1024];

if (argc != 3) {

printf("Usage : %s <username> <passwd>\n",argv[0]); return EXIT_SUCCESS;

}

/* get database connection */

if (get_dbconn(argv[1], argv[2], NULL)) {

return EXIT_FAILURE;

}

EXEC SQL WHENEVER SQLERROR DO branch_ora_err();

Page 18: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Copyright by SunYoung Kim <sunyzero (at) gmail (dot) com>

Method 3 (con't)Method 3 (con't)

sprintf(sqlstmt, "SELECT IDNUM, NAME, AGE, DESCRIPT, UNIQID "

"FROM E_MEMBERS WHERE AGE < :v1");

/* declare cursor with statement */

EXEC SQL PREPARE S FROM :sqlstmt;

EXEC SQL DECLARE C CURSOR FOR S;

/* practice2: 정확한 수치를 찾는 것과 , >, < 에 대한 처리를 추가합시다 .

e.g. 사용자가 '>20' 을 입력하면 20 세 보다 큰 레코드를 검색

e.g. 사용자가 '20' 을 입력하면 정확하게 20 세인 경우만 검색 */

while (1) {

printf("* Search for less than your input age(^d to exit): ");

fflush(stdout);

memset(c_str, 0, sizeof(c_str));

if (fgets(c_str, sizeof(c_str), stdin) == NULL) {

exit(EXIT_SUCCESS);

}

i_age = atoi(c_str);

sprintf(sqlstmt, "SELECT IDNUM, NAME, AGE, DESCRIPT, UNIQID "

"FROM E_MEMBERS WHERE AGE < :v1");

/* declare cursor with statement */

EXEC SQL PREPARE S FROM :sqlstmt;

EXEC SQL DECLARE C CURSOR FOR S;

/* practice2: 정확한 수치를 찾는 것과 , >, < 에 대한 처리를 추가합시다 .

e.g. 사용자가 '>20' 을 입력하면 20 세 보다 큰 레코드를 검색

e.g. 사용자가 '20' 을 입력하면 정확하게 20 세인 경우만 검색 */

while (1) {

printf("* Search for less than your input age(^d to exit): ");

fflush(stdout);

memset(c_str, 0, sizeof(c_str));

if (fgets(c_str, sizeof(c_str), stdin) == NULL) {

exit(EXIT_SUCCESS);

}

i_age = atoi(c_str);

Page 19: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Copyright by SunYoung Kim <sunyzero (at) gmail (dot) com>

Method 3 (con't)Method 3 (con't)

/* open cursor */

EXEC SQL OPEN C USING :i_age;

/* practice1: use indicator for uniqid */

for(i=0; i<MAX_ITERATION; i++) {

/* practice3: using array-fetch (require proc prefetch option) */

EXEC SQL FETCH C

INTO :p_em->idnum,:p_em->name,:p_em->age,:p_em->desc,:p_em->uniqid;

if (SQLCODE == 1403) break;

pr_em(p_em);

}

printf("* fetched row counter: %d\n", sqlca.sqlerrd[2]);

EXEC SQL CLOSE C; /* deallocate cursor space */

}

close_dbconn(1); /* commit work and disconnect from DB */

return EXIT_SUCCESS;

}

/* open cursor */

EXEC SQL OPEN C USING :i_age;

/* practice1: use indicator for uniqid */

for(i=0; i<MAX_ITERATION; i++) {

/* practice3: using array-fetch (require proc prefetch option) */

EXEC SQL FETCH C

INTO :p_em->idnum,:p_em->name,:p_em->age,:p_em->desc,:p_em->uniqid;

if (SQLCODE == 1403) break;

pr_em(p_em);

}

printf("* fetched row counter: %d\n", sqlca.sqlerrd[2]);

EXEC SQL CLOSE C; /* deallocate cursor space */

}

close_dbconn(1); /* commit work and disconnect from DB */

return EXIT_SUCCESS;

}

Page 20: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Copyright by SunYoung Kim <sunyzero (at) gmail (dot) com>

Method 3 (con't)Method 3 (con't) adv. example: "pr6a_method3.pc"

앞의 예제에 다음 기능을 추가해봅시다 .

5 개씩 prefetch 하기 위해서 array 를 사용해봅시다 .

indicator 를 지정할 구조체도 동일하게 5 개씩 array 를 통해서 지정합시다 . (hint!)

#define N_REC_ARRAY 5

...

EXEC SQL OPEN C USING :i_age;

for(i=0, cnt_processed=0; i<MAX_ITERATION; i++) {

EXEC SQL FETCH C

INTO :p_em:p_em_ind;

for(j=0; j<N_REC_ARRAY && j<(sqlca.sqlerrd[2]-cnt_processed); j++) {

pr_em(&p_em[j], &p_em_ind[j]);

}

if (SQLCODE == 1403) break;

cnt_processed = sqlca.sqlerrd[2];

}

EXEC SQL CLOSE C;

#define N_REC_ARRAY 5

...

EXEC SQL OPEN C USING :i_age;

for(i=0, cnt_processed=0; i<MAX_ITERATION; i++) {

EXEC SQL FETCH C

INTO :p_em:p_em_ind;

for(j=0; j<N_REC_ARRAY && j<(sqlca.sqlerrd[2]-cnt_processed); j++) {

pr_em(&p_em[j], &p_em_ind[j]);

}

if (SQLCODE == 1403) break;

cnt_processed = sqlca.sqlerrd[2];

}

EXEC SQL CLOSE C;

Page 21: Oracle Embedded SQL Pro*C : Chap 7 작 성 자 : 김선영 메 일 : sunyzero@gmail.com 버 전 : 1.15 Copyright by SunYoung Kim

Copyright by SunYoung Kim <sunyzero (at) gmail (dot) com>

Method 4Method 4 Method 4

select-list-item 과 input host variable 의 수를 모르는 경우

DESCRIBE 문을 이용함 : select-list-item 와 bind ( 변수저장 ) 정보를 SQLDA 를 이용하여 알아내고 이를 해석하여 데이터를 가져옴

장점

특정 위치로 스크롤이 가능함

memory 의 할당 및 모든 과정이 프로그래머에게 허용됨 .

단점

가장 복잡한 형태의 dynamic SQL

가장 사용 빈도수가 적음