10. 동적 SQL 문#
정적 SQL 문과 동적 SQL 문#
정적 SQL 문#
개념#
사용될 SQL 문은 프로그래머에 의해 미리 결정되고 고정된다. 결정된 SQL 문은 일련의 내장 SQL 문처럼 프로그램에 "하드-코드(hard-coded)"된다. 정적 SQL 문에 대한 자세한 내용은 6장과 8장을 참조하기 바란다.
단점#
-
사용될 SQL 문을 미리 결정할 수 없는 프로그램에서는 사용할 수 없다.
-
참조되는 테이블과 칼럼들이 프로그래머에 의해 미리 결정되어야 한다. 즉, 테이블명이나 칼럼명의 위치에는 호스트 변수를 사용할 수 없다.
-
정적 SQL 문의 입력 호스트 변수들은 약간의 유연성은 제공하지만 근본적으로 자체 고정적인 본질은 바꾸지 못한다.
동적 SQL 문#
개념#
프로그램의 실행시간(run-time)에 SQL 문의 텍스트를 메모리 영역 (즉, 문자 타입 변수)에 구성한다. 따라서 SQL 문을 프로그램 소스 코드로 하드-코드 하지 않아도 된다.
장점#
-
사용될 SQL 문을 프로그램에서 미리 결정하지 않아도 된다. 즉, 동적인 SQL 문의 사용이 가능하다.
-
참조되는 테이블 및 칼럼을 실행 시간에 동적으로 결정할 수 있다.
단점#
- 사용될 SQL 문과 참조되는 테이블 및 칼럼을 실행 시간에 알 수 있으므로, 성능면에서는 정적 SQL 문보다 비효율적이다.
동적 SQL 문의 종류#
Altibase는 4가지의 동적 SQL 문의 사용을 지원한다. 동적 SQL 문을 사용하여 응용 프로그램을 구현할 때, 각 메소드 별로 아래 설명된 순서로 내장 SQL 문을 사용하면 된다.
메소드 1#
이 메소드는 EXECUTE SQL IMMEDIATE 구문 하나로만 구성된다.
자주 사용되는 SQL 문에 이 메소드를 사용한다면 성능 저하를 초래하는 등 비효율적이다.
실행 시간에 SQL 문(테이블 명, 칼럼 명 등)이 결정되는 DDL문에 효과적이다.
SELECT 문 실행에는 사용할 수 없다.
구문#
EXEC SQL EXECUTE IMMEDIATE <:host_var | string_literal>;
인자#
- <:host_var>
SQL 문 전체 문자열을 포함하는 변수 - <string_literal>
고정된 SQL 문 전체 문자열
설명#
호스트 변수를 사용할 경우 하나의 호스트 변수만 사용해야 한다. 이 호스트 변수는 SQL 문 전체 문자열을 포함하는 변수를 말한다. 또한 이 SQL 문 전체 스트링은 호스트 변수 또는 호스트 변수로 대체될 파라미터 마커(Parameter Maker)인 물음표("?")를 포함할 수 없다.
예제#
[예제 1] 다음은 고정된 SQL 문 스트링을 이용하는 동적 SQL 문 메소드 1의 사용 예를 보여준다.
< 예제 프로그램 : dynamic1.sc >
EXEC SQL EXECUTE IMMEDIATE DROP TABLE T1;
EXEC SQL EXECUTE IMMEDIATE CREATE TABLE T1 (I1 INTEGER, I2 INTEGER);
[예제 2] 다음은 호스트 변수를 이용하는 동적 SQL 문 메소드 1의 사용 예를 보여준다.
< 예제 프로그램 : dynamic1.sc >
char query[100];
strcpy(query, "drop table t2");
EXEC SQL EXECUTE IMMEDIATE :query;
strcpy(query, "create table t2(i1 integer)");
EXEC SQL EXECUTE IMMEDIATE :query;
메소드 2#
메소드 2는 PREPARE 문과 EXECUTE 문의 2단계로 수행되며, 한 번 prepare된 SQL 문을 여러 번 execute하는 경우 유용하다.
PREPARE 문에서 사용될 SQL 문 문자열은 파라미터 마커(Parameter Maker)인 물음표("?")를 포함할 수 있으며, 이 파라미터 마커는 EXECUTE 문의 호스트 변수로 치환된다.
EXECUTE 문은 항상 가장 최근에 PREPARE된 구문을 수행한다. 즉, PREPARE 문과 EXECUTE 문 사이에 prepare 된 SQL 문이 변경되더라도, 다시 PREPARE 문을 수행하기 전까지는, 이전의 PREPARE 문에서 사용한 SQL 문을 EXECUTE 문에서 수행한다.
SQL 문을 자주 변경하면서 PREPARE, EXECUTE 문을 수행한다면 성능저하를 초래하는 등 비효율적이다.
실행시간에 SQL 문이 결정되는 INSERT, UPDATE, DELETE문에 효과적이다.
SELECT 문 실행에는 사용할 수 없다.
Note: PREPARE 문 전에 DECLARE STATEMENT 문을 수행해도 무방하다.
PREPARE#
구문#
EXEC SQL PREPARE <statement_name> FROM
<:host_var | string_literal>;
인자#
- <statement_name>
SQL 문 식별자. 알파벳(a~z, A~Z), 밑줄("_"), 또는 달러 기호("$")로 시작하여야 하며, 그 길이는 최대 50 bytes로 제한된다. - <:host_var>
SQL 문 전체 문자열을 포함하는 문자형 타입의 변수 - <string_literal>
고정된 SQL 문 전체 문자열
설명#
SQL 문을 수행하기 위한 준비를 한다.
한 프로그램 내에서 같은 SQL 문 식별자를 하나 이상의 PREPARE 문에서 사용한 경우, 실행시간에 EXECUTE 문이 호출될 때 가장 최근에 실행한 PREPARE 문의 SQL 문을 수행한다.
SQL 문은 SELECT 문일 수 없다.
예제#
다음은 조건에 따라 실행시간에 SQL 문이 결정되고 그 SQL 문으로 PREPARE 하는 예를 보여준다.
< 예제 프로그램 : dynamic2.sc >
char query[100];
EXEC SQL BEGIN DECLARE SECTION;
int s_eno;
EXEC SQL END DECLARE SECTION;
if (s_eno < 20)
{
strcpy(query, "delete from employees where eno = ? and e_lastname = ?");
}
else
{
strcpy(query, "insert into employees(eno, e_lastname) values (?, ?)");
}
EXEC SQL PREPARE S FROM :query;
EXECUTE#
구문#
EXEC SQL EXECUTE <statement_name>
[ USING <host_var_list> ];
인자#
- <statement_name>
SQL 문 식별자 - <host_var_list>
입력 호스트 변수와 입력 지시자 변수 리스트
설명#
미리 준비된 SQL 문을 수행한다.
PREPARE 문 후에 수행가능하다. 정의되지 않은 SQL 문 식별자로 EXECUTE 문을 수행할 경우 "The statement does not exist." 오류가 발생한다.
지정한 SQL 문 식별자의 SQL 문은 SELECT 문일 수 없다.
EXECUTE 문 수행시에 각 파라미터 마커를 통해서 대응하는 변수의 값이 전달된다. 이 값은 USING절에 호스트 변수 리스트를 사용하여 지정할 수 있다. 이 때, USING절의 호스트 변수의 개수는 수행하고자 하는 SQL 문의 파라미터 마커의 개수와 같아야 하고, 호스트 변수의 타입은 대응되는 칼럼의 타입과 호환 가능해야 한다.
한 프로그램 내에서 같은 SQL 문 식별자를 하나 이상의 PREPARE 문에서 사용한 경우, 실행시간에 가장 최근에 수행한 PREPARE 문의 SQL 문을 수행한다.
예제#
다음 예제는 EXECUTE 문의 사용 예를 보여준다.
< 예제 프로그램 : dynamic2.sc >
EXEC SQL BEGIN DECLARE SECTION;
int s_eno;
char s_ename[20+1];
EXEC SQL END DECLARE SECTION;
s_eno = 10;
strcpy(s_ename, "YHBAE");
EXEC SQL EXECUTE S USING :s_eno, :s_ename;
메소드 3#
메소드 3은 PREPARE 문과 DECLARE CURSOR 문, OPEN 문, FETCH 문, CLOSE 문의 5단계로 구성된다.
이 메소드는 SELECT 문을 실행할 수 있는 유일한 동적 SQL 실행 방법이다.
PREPARE 문보다 DECLARE CURSOR 문을 먼저 사용할 때는, DECLARE STATEMENT 문을 DECLARE CURSOR 문 이전에 수행해야 한다.
DECLARE STATEMENT#
구문#
EXEC SQL DECLARE <statement_name> STATEMENT;
인자#
- <statement_name>
SQL 문 식별자. 알파벳(a~z, A~Z), 밑줄("_"), 또는 달러 기호("$")로 시작하여야 하며, 그 길이는 최대 50 bytes로 제한된다.
설명#
이 구문은 다른 내장 SQL 문에서 사용하는 SQL 문 식별자를 선언한다.
이 구문은 DECLARE CURSOR 문이 PREPARE 문 앞에 수행될 때, DECLARE CURSOR 전에 사용해야 한다. PREPARE 문이 DECLARE CURSOR 앞에 위치할 때는 이 구문을 사용하지 않아도 된다.
예제#
다음 예제는 DECLARE CURSOR 문이 PREPARE 문에 앞서 실행될 때, DECLARE STATEMENT를 사용하는 것을 보여준다.
EXEC SQL DECLARE sql_stmt STATEMENT;
EXEC SQL DECLARE emp_cursor CURSOR FOR sql_stmt;
EXEC SQL PREPARE sql_stmt FROM :dyn_string;
PREPARE#
구문#
EXEC SQL PREPARE <statement_name> FROM
<:host_var | string_literal>;
인자#
- <statement_name>
SQL 문 식별자. 최대 50자까지 허용 - <:host_var>
SQL 문 전체 문자열을 포함하는 변수 - <string_literal>
고정된 SQL 문 전체 문자열
설명#
SQL 문을 수행하기 위한 준비를 한다.
한 프로그램 내에서 같은 SQL 문 식별자를 하나 이상의 PREPARE 문에서 사용한 경우, 실행시간에 DECLARE문이 호출되면, 가장 최근에 실행한 PREPARE 문의 SQL 문으로 커서를 선언한다.
SQL 문은 SELECT 문이어야 한다.
예제#
다음은 조건에 따라 실행시간에 SQL 문이 결정되고 그 SQL 문으로 PREPARE 하는 예를 보여준다.
< 예제 프로그램 : dynamic3.sc >
EXEC SQL BEGIN DECLARE SECTION;
char query[100];
EXEC SQL END DECLARE SECTION;
int type;
switch (type)
{
case 1:
strcpy(query, "select * from departments");
break;
case 2:
strcpy(query, "select * from goods");
break;
case 3:
strcpy(query, "select * from orders");
break;
}
EXEC SQL PREPARE S FROM :query;
DECLARE CURSOR#
구문#
EXEC SQL DECLARE <cursor_name> CURSOR FOR
<statement_name>;
인자#
- <cursor_name>
커서 이름 - <statement_name>
SQL 문 식별자
설명#
지정한 SQL 문 식별자로 커서를 선언한다.
PREPARE 문, CLOSE 문, CLOSE RELEASE 문 후에 수행가능하다. 정의되지 않은 SQL 문 식별자로 커서 선언문을 수행할 경우 "The statement does not exist" 오류가 발생한다.
지정한 SQL 문 식별자의 SQL 문은 SELECT 문이어야 한다.
한 프로그램 내에서 같은 SQL 문 식별자를 하나 이상의 PREPARE 문에서 사용한 경우, 실행시간에 가장 최근에 실행한 PREPARE 문의 SQL 문으로 커서를 선언한다.
예제#
다음은 SQL 문 식별자 S로 커서 CUR을 선언하는 예를 보여준다.
< 예제 프로그램 : dynamic3.sc >
EXEC SQL DECLARE CUR CURSOR FOR S;
OPEN#
구문#
EXEC SQL OPEN <cursor_name> [ USING <host_var_list> ];
인자#
- <cursor_name>
커서 이름 - <host_var_list>
입력 호스트 변수, 입력 지시자 변수 리스트
설명#
OPEN 문에서는 커서 선언문의 SQL 문을 수행한다.
커서 OPEN 문은 커서 선언문 또는 커서 CLOSE 문 후에 수행가능하다. 선언되지 않은 커서를 OPEN할 경우 "The cursor does not exist." 오류가 발생한다.
OPEN 문을 실행할 때, 각 파라미터 마커를 통해서 대응하는 변수의 값을 전달한다. 이 값은 USING절에 호스트 변수 리스트를 사용하여 지정할 수 있다. 이 때, USING절의 호스트 변수의 개수는 수행하고자 하는 SQL 문의 파라미터 마커의 개수와 같아야 하고, 호스트 변수의 타입은 대응되는 칼럼의 타입과 호환 가능해야 한다.
같은 커서 이름이 하나 이상 선언된 경우, 실행시간에 가장 최근에 선언된 커서를 참조한다.
제한 사항#
SELECT 문의 제한 사항이 그대로 적용된다.
예제#
다음은 커서 CUR을 OPEN하는 예를 보여준다.
< 예제 프로그램 : dynamic3.sc >
EXEC SQL OPEN CUR;
FETCH#
구문#
EXEC SQL FETCH <cursor_name> INTO <host_var_list>;
인자#
- <cursor_name>
커서 이름 - <host_var_list>
출력 호스트 변수와 출력 지시자 변수 리스트
설명#
커서 FETCH 문은 커서 OPEN 문 후에 수행가능하다. OPEN하지 않은 커서를 FETCH할 경우 "Function sequence error" 오류가 발생한다.
커서 OPEN 후 그 결과값을 받아오기 위해 사용한다. 결과값을 받아오기 위한 방법은 INTO절에 호스트 변수 리스트를 지정해 주는 것이다. 이 때, INTO절의 호스트 변수의 개수는 SELECT절의 칼럼 개수와 같아야 하고, 각 호스트 변수의 타입은 대응되는 칼럼의 타입과 호환 가능해야 한다.
같은 커서 이름이 하나 이상 선언된 경우, 실행시간에 가장 최근에 선언된 커서를 참조한다.
예제#
다음은 조건에 따라 커서 CUR의 출력 호스트 변수를 변경하면서 FETCH하는 예를 보여준다. 각 호스트 변수마다 지시자 변수를 지정함으로써 NULL 체크가 가능하다. while 루프 안에서 SQL_NO_DATA가 반환될 때까지 FETCH한다.
< 예제 프로그램 : dynamic3.sc >
int type;
/* declare host variables */
EXEC SQL BEGIN DECLARE SECTION;
/*declare output host variables */
department s_department;
goods s_goods;
orders s_orders;
/*declare indicator variables */
dept_ind s_dept_ind;
good_ind s_good_ind;
order_ind s_order_ind;
EXEC SQL END DECLARE SECTION;
while(1)
{
/* use indicator variables to check null value */
switch (type)
{
case 1:
EXEC SQL FETCH CUR
INTO :s_department :s_dept_ind;
break;
case 2:
EXEC SQL FETCH CUR
INTO :s_goods :s_good_ind;
break;
case 3:
EXEC SQL FETCH CUR
INTO :s_orders :s_order_ind;
break;
}
if (sqlca.sqlcode == SQL_SUCCESS)
{
cnt++;
}
else if (sqlca.sqlcode == SQL_NO_DATA)
{
printf("%d rows selected\n\n", cnt);
break;
}
else
{
printf("Error : [%d] %s\n\n",
SQLCODE, sqlca.sqlerrm.sqlerrmc);
break;
}
}
CLOSE#
구문#
EXEC SQL CLOSE <cursor_name>;
인자#
- <cursor_name>
커서 이름
설명#
커서 CLOSE 문은 커서 선언문, 커서 OPEN 문, 커서 FETCH 문 후에 수행 가능하다. 선언되지 않은 커서를 CLOSE할 경우 "The cursor does not exist." 오류가 발생한다.
FETCH를 끝까지 하지 않은 상태에서 커서 CLOSE 문 실행시, 서버에 남아 있는 결과들을 삭제한다. 이 때 커서에 할당된 자원은 해제되지 않는다. 따라서 커서 CLOSE 문 수행 후 커서 선언문은 생략하고 바로 OPEN 문 수행이 가능하다.
같은 커서 이름이 하나 이상 선언된 경우, 실행시간에 가장 최근에 선언된 커서를 참조한다.
예제#
다음은 커서 CUR을 CLOSE하는 예를 보여준다.
< 예제 프로그램 : dynamic3.sc >
EXEC SQL CLOSE CUR;
CLOSE RELEASE#
구문#
EXEC SQL CLOSE RELEASE <cursor_name>;
인자#
- <cursor_name>
커서 이름
설명#
커서 CLOSE RELEASE 문은 커서 선언문, 커서 OPEN 문, 커서 FETCH 문, 커서 CLOSE 문 후에 수행 가능하다. 선언되지 않은 커서를 CLOSE RELEASE할 경우 "The cursor does not exist." 오류가 발생한다.
FETCH를 끝까지 하지 않은 상태에서 커서 CLOSE RELEASE 문 실행시, 서버에 남아 있는 결과들을 삭제한다. 또한 커서에 할당된 모든 자원을 해제한다. 따라서 커서 CLOSE RELEASE 문 수행 후에는 커서 선언문, 커서 OPEN 문 순서로 수행하여야 한다. 즉, 커서 CLOSE RELEASE 문 후에 커서 OPEN 문을 수행할 수 없다.
커서를 재사용한다면 CLOSE 문을, 재사용하지 않는다면 CLOSE RELEASE 문을 사용하기를 추천한다. 일반적으로 커서를 일회용으로 사용하는 경우는 거의 없으므로 커서 CLOSE RELEASE 문은 거의 사용되지 않는다. 만약 계속해서 재사용될 커서를 CLOSE RELEASE, 커서 선언문, 커서 OPEN 문 순으로 수행한다면 성능 저하를 초래하게 된다.
같은 커서 이름이 하나 이상 선언된 경우, 실행시간에 가장 최근에 선언된 커서를 참조한다.
예제#
다음 예제는 커서 CUR을 CLOSE하고 CUR에 할당된 자원을 해제한다.
EXEC SQL CLOSE RELEASE CUR;
메소드 4#
메소드 4는 PREPARE 문과 EXECUTE 문으로 구성하는 메소드 2 방식과 PREPARE 문, DECLARE CURSOR 문, OPEN 문, FETCH 문, CLOSE 문으로 구성하는 메소드 3을 지원한다.
메소드 2와 메소드 3은 SQL 문자열에 사용될 파라미터 마커를 컴파일 단계에서 지정하는 반면에 메소드 4는 프로그램 수행 중에 파라미터 마커를 설정한다.
SQLDA 구조체#
SQLDA는 파라미터 마커에 바인드되는 변수의 정보를 저장하는 구조체이다. 형태는 아래와 같다. 구조체의 파라미터 변수에 대한 설명은 부록 C를 참조하기 바란다.
struct SQLDA
{
int N; /* 명령을 실행할 column의 개수 */
char **V; /* 데이터의 주소 */
int *L; /* 각 데이터 buffer 길이 */
short *T; /* 각 데이터 type */
short **I; /* indicator 주소 */
int F; /* 분석된 column 개수 */
}
- SQLSQLDAAlloc(int allocSize) 함수
SQLDA 구조체를 사용하여 메모리를 할당한다. 사용자는 최대 allocSize값으로 최대 바인드 값을 설정한다. - SQLSQLDAFree( SQLDA *sqlda ) 함수
SQLDA 구조체를 메모리에서 해제한다.
다음의 그림은 각각 Bind Variables 함수와 Select List 함수 사용에 대한 SQLDA 구조체의 변화를 설명하고 있다.
동작 순서#
INSERT, UPDATE, DELETE 구문 실행 시 순서#
- CONNECT: DB에 접속한다.
- SQLDA 를 초기화한다.
- PREPARE: 동적 쿼리 입력을 위한 준비를 한다.
- BIND VARIABLES: SQL 문이 포함하고 있는 파라미터 마커의 정보를 얻는다.
- BIND VARIABLES 을 통해 얻은 파라미터 정보에 해당하는 데이터를 SQLDA에 저장한다.
- EXECUTE: 쿼리를 수행한다.
SELECT 구문 실행 시 순서#
- CONNECT: DB에 접속한다.
- SQLDA를 초기화한다.
- PREPARE: 동적 쿼리 입력을 위한 준비를 한다.
- DECLARE CURSOR: 커서를 선언한다.
- BIND VARIABLES: SQL 문의 파라미터 마커 정보를 얻는다.
- BIND VARIABLES을 통해 얻은 파라미터 정보에 해당하는 데이터를 SQLDA 구조체에 저장한다.
- OPEN CURSOR: 커서를 연다.
- SELECT LIST: SQL 문의 칼럼 정보를 얻는다.
- SELECT LIST을 통해 얻은 내용에 대한 FETCH정보를 SQLDA 구조체에 저장한다.
- FETCH: 커서를 이용하여 쿼리를 수행한다.
ARRAY SIZE SET#
구문#
EXEC SQL FOR <statement_name> <:host_var>;
인자#
- <statement_name>
SQL 문 식별자. 알파벳(a~z, A~Z), 밑줄("_"), 또는 달러 기호("$")로 시작하여야 하며, 그 길이는 최대 50 bytes로 제한된다. - <:host_var>
한번에 처리 할 배열의 크기
설명#
한번에 처리할 행의 개수를 지정한다. INSERT문, UPDATE문, DELETE문 실행을 위한 배열 크기이다.
예제#
#define ARRAY_SIZE 3
/* declare host variables */
EXEC SQL BEGIN DECLARE SECTION;
int arrSize = ARRAY_SIZE;
EXEC SQL END DECLARE SECTION;
EXEC SQL FOR INSERT_STMT :arrSize;
BIND VARIABLES#
구문#
EXEC SQL DESCRIBE BIND VARIABLES FOR <statement_name> INTO <:sqlda_var>;
인자#
- <statement_name>
SQL 문 식별자. 알파벳(a~z, A~Z), 밑줄("_"), 또는 달러 기호("$")로 시작하여야 하며, 그 길이는 최대 50 bytes로 제한된다. - <:sqlda_var >
SQLDA 구조체 변수의 이름이며 <:host_var>와 같은 타입이다.
설명#
PREPARE 문 수행에서 사용된 SQL 문의 파라마터 마커 정보를 얻어온다.
예제#
/* bind variables initialization */
bindInfo = (SQLDA*) SQLSQLDAAlloc( MAX_COLUMN_SIZE );
bindInfo->N = MAX_COLUMN_SIZE;
EXEC SQL DESCRIBE BIND VARIABLES FOR S INTO :bindInfo;
CURSOR OPEN#
구문#
EXEC SQL OPEN <cursor_name> USING DESCRIPTOR <:sqlda_var>;
인자#
- <cursor_name>
커서 이름 - <:sqlda_var >
SQLDA 구조체 변수의 이름이며 <:host_var>와 같은 타입이다.
설명#
커서를 연다.
예제#
EXEC SQL OPEN CUR USING DESCRIPTOR :bindInfo;
/* check sqlca.sqlcode */
if(sqlca.sqlcode != SQL_SUCCESS)
{
printf("Error : [%d] %s\n\n", SQLCODE, sqlca.sqlerrm.sqlerrmc);
}
EXECUTE#
구문#
EXEC SQL EXECUTE <statement_name> USING DESCRIPTOR <:sqlda_var>;
인자#
- <statement_name>
SQL 문 식별자. 알파벳(a~z, A~Z), 밑줄("_"), 또는 달러 기호("$")로 시작하여야 하며, 그 길이는 최대 50 bytes로 제한된다. - <:sqlda_var >
SQLDA 구조체 변수의 이름이며 <:host_var>와 같은 타입이다.
설명#
SQL 문을 실행한다. PREPARE 문 후에 수행 가능하며, SQL 문을 입력하지 않고 수행할 경우에는 "The statement does not exist." 오류가 발생한다. :sqlda_var에는 파라미터 마커에 해당하는 값이 설정되어 있어야 한다.
예제#
EXEC SQL EXECUTE S USING DESCRIPTOR :bindInfo;
/* check sqlca.sqlcode */
if(sqlca.sqlcode == SQL_SUCCESS)
{
printf("\nEXECUTE SUCCESS\n\n");
}
else
{
printf("Error : [%d] %s\n\n", SQLCODE, sqlca.sqlerrm.sqlerrmc);
}
FETCH#
구문#
EXEC SQL FETCH <cursor_name> USING DESCRIPTOR <:sqlda_var>;
인자#
- <cursor_name>
커서 이름 - <:sqlda_var >
SQLDA 구조체 변수의 이름이며 <:host_var>와 같은 타입이다.
설명#
커서를 이동하여 결과값을 얻어온다. 커서를 열고 난 후에 수행할 수 있으며 결과 값을 저장할: sqlda_var변수를 지정한다. 열지 않은 커서를 FETCH할 경우 "Function sequence error" 오류가 발생한다.
예제#
while(1)
{
EXEC SQL FETCH CUR USING DESCRIPTOR :selectInfo;
if( sqlca.sqlcode == SQL_SUCCESS || sqlca.sqlcode == SQL_SUCCESS_WITH_INFO )
{
printf("\n");
for( i=0; i < selectInfo->N ; i++)
{
if( *(SQLLEN*)(selectInfo->I[i]) == -1 )
{
printf("NULL ");
}
else
{
printf("%s ", selectInfo->V[i]);
}
}
}
else if( sqlca.sqlcode == SQL_NO_DATA)
{
break;
}
else
{
printf("Error : [%d] %s\n\n", SQLCODE, sqlca.sqlerrm.sqlerrmc);
break;
}
}
예제 프로그램#
dynamic1.sc#
$ALTIBASE_HOME/sample/APRE/dynamic1.sc 참고
실행결과#
$ is -f schema/schema.sql
$ make dynamic1
$ ./dynamic1
<DYNAMIC SQL METHOD 1>
------------------------------------------------------
[Using String Literal]
------------------------------------------------------
Success execution with string literal
------------------------------------------------------
[Using Host Variable]
------------------------------------------------------
Success execution with host variable
dynamic2.sc#
$ALTIBASE_HOME/sample/APRE/dynamic2.sc 참고
실행결과#
$ is -f schema/schema.sql
$ make dynamic2
$ ./dynamic2
<DYNAMIC SQL METHOD 2>
------------------------------------------------------
[Prepare]
------------------------------------------------------
Success prepare
------------------------------------------------------
[Execute]
------------------------------------------------------
Success execute
dynamic3.sc#
$ALTIBASE_HOME/sample/APRE/dynamic3.sc 참고
실행결과#
$ is -f schema/schema.sql
$ make dynamic3
$ ./dynamic3
<DYNAMIC SQL METHOD 3>
------------------------------------------------------
[Prepare]
------------------------------------------------------
Success prepare
------------------------------------------------------
[Declare Cursor]
------------------------------------------------------
Success declare cursor
------------------------------------------------------
[Open Cursor]
------------------------------------------------------
Success open cursor
------------------------------------------------------
[Fetch Cursor]
------------------------------------------------------
30 rows selected
------------------------------------------------------
[Close Cursor]
------------------------------------------------------
Success close cursor
dynamic4.sc#
$ALTIBASE_HOME/sample/APRE/dynamic4.sc 참고
실행결과#
$ is -f schema/schema.sql
$ make dynamic4
$ ./dynamic4
<DYNAMIC SQL METHOD 4>
iSQL> insert into DEPARTMENTS values(?,?,?,?)
Enter value for 0 bind variable : 1
Enter value for 1 bind variable : 2
Enter value for 2 bind variable : 3
Enter value for 3 bind variable : 4
EXECUTE SUCCESS
iSQL> select * from DEPARTMENTS
1 2 3 4
iSQL> delete from DEPARTMENTS where DNO=?
Enter value for 0 bind variable : 1
EXECUTE SUCCESS
iSQL> select * from DEPARTMENTS
iSQL> exit