콘텐츠로 이동

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문을 DELCARE 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