B. 부록: Proc*C에서 APRE로 변환#
이 부록은 오라클의 pro*C(C++)로 작성된 응용 프로그램을 Altibase C/C++ Precompiler 응용 프로그램으로 전환할 때 참조한다.
데이터 타입 비교#
오라클에서 사용되는 데이터 타입과 여기에 대응되는 Altibase의 데이터 타입의 종류를 설명한다.
데이터 타입 비교표#
| ODBC SQL data type | 오라클 | Altibase | 비 고 |
|---|---|---|---|
| SQL_CHAR | CHAR | CHAR | 1-32000 length |
| SQL_TIMESTAMP | DATE | DATE | |
| SQL_LONGVARCHAR | LONG | BLOB | 2147483647 바이트까지 가능 |
| SQL_INTEGER | INT | INTEGER | |
| SQL_FLOAT | NUMBER | NUMBER | |
| SQL_DECIMAL | NUMBER(P) | NUMBER(P) | 1-38 |
| SQL_DECIMAL | NUMBER(P,S) | NUMBER(P,S) | precision : 1-38 scale : -84 – 126 |
| SQL_BINARY | RAW | HSS_BYTES | 1-32000 |
| SQL_VARCHAR | VARCHAR | VARCHAR | max 32000 bytes |
| SQL_VARCHAR | VARCHAR2 | VARCHAR | max 32000 bytes |
내장 함수 비교#
오라클과 마찬가지로 Altibase 역시 숫자함수, 날짜함수, 문자열함수, 데이터 타입 변환함수 및 기타 내장함수(Built-in function)를 제공한다. 오라클에 대응하는 Altibase의 데이터 타입 변환 함수와 내장 함수를 설명한다.
내장 함수(Built-in Function) 비교#
오라클에서 사용되는 함수의 이름, 용도, 사용법이 유사하다.
Altibase에서 지원하는 함수의 종류는 다음과 같다.
- 숫자 함수: ABS, ACOS, ASIN, ATAN, ATAN2, CEIL, COS, COSH, EXP, FLOOR, ISNUMERIC, LN, LOG, MOD, POWER, RANDOM, ROUND, SIGN, SIN, SINH, SQRT, TAN, TANH, TRUNC, BITTAND, BITOR, BITXOR, BITNOT
- 그룹 함수: AVG, COUNT, GROUP_CONCAT, LISTAGG, MAX, MIN, PERCENTILE_CONT, PERCENTILE_DISC, STATS_ONE_WAY_ANOVA, STDDEV, STDDEV_POP, STDDEV_SAMP, SUM, VARIANCE, VAR_POP, VAR_SAMP
- 문자열 함수: ASCII, CHAR_LENGTH, CHOSUNG, CHR, CONCAT, DIGITS, INITCAP, INSTR, INSTRB, POSITION, LOWER, LPAD, LTRIM, NCHR, OCTET_LENGTH, PKCS7PAD16, PKCS7UNPAD16, RANDOM_STRING, REGEXP_COUNT, REGEXP_INSTR, REGEXP_SUBSTR, REPLACE2, REVERSE_STR, RPAD, RTRIM, SIZEOF, SUBSTR, TRANSLATE, TRIM, UPPER, REPLICATE, REVERSE_STR, STUFF, UPPER
- 날짜 함수: ADD_MONTHS, CURRENT_DATE, CURRENT_TIMESTAMP, CONV_TIMEZONE, DATEADD, DATEDIFF, DATENAME, DB_TIMEZONE, EXTRACT, LAST_DAY, MONTHS_BETWEEN, ROUND, NEXT_DAY, SESSION_TIMEZONE, SYSDATE, SYSTIMESTAMP, TRUNC, UNIX_DATE, UNIX_TIMESTAMP
- 데이터 타입 변환 함수: ASCIISTR, BIN_TO_NUM, CONVERT, DATE_TO_UNIX, HEX_ENCODE, HEX_DECODE, HEX_TO_NUM, OCT_TO_NUM, TO_BIN, TO_CHAR, TO_DATE, TO_HEX, TO_NCHAR, TO_NUMBER, TO_OCT, TO_RAW, UNISTR, UNIX_TO_DATE
- 암호화 함수: AESDECRYPT, AESENCRYPT, DESENCRYPT, DESDECRYPT, TDESDECRYPT/TRIPLE_DESDECRYPT,TDESENCRYPT/TRIPLE_DESENCRYPT
- 윈도우 함수: AVG, COUNT, LISTAGG, MAX, MIN, PERCENTILE_CONT, PERCENTILE_DISC, STDDEV, SUM, VARIANCE, GROUP_CONCAT, RANK, DENSE_RANK, ROW_NUMBER, LAG, LEAD, FIRST_VALUE, LAST_VALUE, NTH_VALUE
- 기타 함수: BINARY_LENGTH, CASE2, CASE_WHEN, COALESCE, DECODE, DIGEST, DUMP, GREATEST, GROUPING, GROUPING_ID, HOST_NAME, LEAST, LNNVL, NULLIF, NVL, NVL2, RAW_SIZEOF, RAW_CONCAT, ROWNUM, NVL, NVL2, SENDMSG, SUBRAW, SYS_CONNECT_BY_PATH, USER_ID, USER_NAME, SESSION_ID
함수들에 대한 보다 자세한 설명은 SQL Reference을 참조한다.
데이터베이스 연결/해제#
오라클과 Altibase에 연결하고 해제하는 방법을 비교 설명한다.
데이터베이스 연결#
오라클과 Altibase의 default connection 문법은 동일하며 connection name을 부여하여 multi connection도 가능하다. 오라클과 마찬가지로 USING을 사용하여 연결 옵션을 설정할 수 있다.
Connect Statement#
- 오라클
EXEC SQL CONNECT {:user IDENTIFIED BY :oldpswd :usr_psw }
[[ AT { dbname | :host_variable }] USING :connect_string ];
- Altibase
EXEC SQL [AT {conn_name | :conn_name}]
CONNECT <:user> IDENTIFIED BY <:passwd>
[USING <:conn_opt>[,<:conn_opt2>]];
Default Connection 연결 예제#
- 오라클
char *username = "SCOTT";
char *password = "TIGER";
char *connstr = “ORA817”;
EXEC SQL WHENEVER SQLERROR
.
.
.
EXEC SQL CONNECT :username IDENTIFIED BY :password
USING :connstr;
- Altibase
strcpy(username, "SYS");
strcpy(password, "MANAGER");
strcpy(connstr,“DSN=192.168.1.2;PORTNO=20310;CONNTYPE=3”);
EXEC SQL CONNECT :username IDENTIFIED BY :password
USING :connstr;
- Using 절이 없을 경우 응용프로그램이 수행되는 시스템의 Altibase로 연결하게 된다.
Named Connection 연결 예제#
- 오라클
char *username = "SCOTT";
char *password = "TIGER";
char *connstr = “ORA817”;
EXEC SQL WHENEVER SQLERROR
.
.
.
EXEC SQL CONNECT :username IDENTIFIED BY :password
AT :db_name USING :connstr;
- Altibase
strcpy(user2, "ALTIBASE");
strcpy(passwd2, "ALTIBASE");
strcpy(conn_name, "CONN2");
strcpy(connstr,“DSN=192.168.1.12;PORTNO=20310;CONNTYPE=1”);
EXEC SQL AT :conn_name CONNECT :user2 IDENTIFIED BY :passwd2
USING :connstr;
데이터베이스 연결 해제#
오라클은 롤백을 실행하면서 연결 해제를 실행하는 하나의 문장(EXEC SQL ROLLBACK WORK RELEASE )은 지원한다.
Altibase도 이 문장을 지원한다.
Disconnect Statement#
- 오라클
EXEC SQL COMMIT WORK RELEASE;
또는
EXEC SQL ROLLBACK WORK RELEASE;
- Altibase
EXEC SQL COMMIT WORK RELEASE;
또는
EXEC SQL ROLLBACK WORK RELEASE;
호스트 변수#
오라클의 pro*C와 Altibase의 Precompiler에서 사용되는 호스트 변수(Host Variables)를 비교하고 차이점을 설명한다.
호스트 변수 타입 비교#
| 오라클 | Altibase | 비 고 | ||
|---|---|---|---|---|
| Database Column type | Host Variable C type | Database Column type | Host Variable C type | |
| CHAR | char | CHAR | char/char[2] | single character |
| VARCHAR2(X) VARCHAR(X) | VARCHAR[X] | VARCHAR | VARCHAR | n-byte variable-length character array |
| CHAR[X] | char[x] | CHAR[X] | char[x] | n-byte character array |
| NUMBER | int | NUMBER/ INTEGER | int/ APRE _INT | integer |
| NUMBER(P,S) | short int long float double | NUMBER(P,S) | short int/APRE_INTEGER long float double | small integer integer large integer float-point number double-precision floating-point number |
| DATE | char[n] varchar[n] | DATE | char[n] varchar[n] | n >= 20 |
호스트 변수 선언부#
선언부의 구문은 오라클과 Altibase가 같은 형식이다.
- 오라클
EXEC SQL BEGIN DECLARE SECTION;
/* 호스트 변수 선언 */
EXEC SQL END DECLARE SECTION;
- Altibase
EXEC SQL BEGIN DECLARE SECTION;
/* 호스트 변수 선언 */
EXEC SQL END DECLARE SECTION;
내장 SQL문#
Altibase Precompiler와 오라클 pro*C의 기본 SQL(SELECT, UPDATE, INSERT, DELETE)과 커서 처리 SQL문, 동적 SQL 문을 비교 설명한다.
기본 DML문#
Select, Insert, Update, Delete 모두 오라클과 Altibase에서의 사용 방법이 동일하다.
커서 처리 SQL문#
기본적인 커서의 선언 방법은 오라클과 Altibase에서 동일하다. 다만, Altibase는 오라클처럼 커서 이름에 호스트 변수를 사용하는 방법을 지원하지 않는다.
커서 선언#
- 오라클
EXEC SQL DECLARE cur_emp CURSOR FOR
SELECT ename, job, sal
FROM emp;
- Altibase
EXEC SQL DECLARE cur_emp CURSOR FOR
SELECT ename, job, sal
FROM emp;
커서의 Open 과 fetch#
커서의 open과 fetch는 오라클과 동일하다. 오라클과 Altibase 간의 에러 코드의 종류와 값이 다르므로 fetch문 안에서의 에러 처리 코드는 변경되어야 한다. 실행 시간 에러 처리를 위한 WHENEVER 문인 EXEC SQL WHENEVER NOT FOUND DO BREAK; 는 오라클과 동일한 사용법으로 지원한다.
- 오라클
EXEC SQL OPEN cur_emp;
if(sqlca.sqlcode != SQL_OK ) {
fprintf(stderr, "OPEN CSR ERROR%d\n",sqlca.sqlcode);
close_db();
exit(0);
}
for(;;)
{
EXEC SQL FETCH cur_emp
INTO :emp_name, :job_title, :salary;
switch(sqlca.sqlcode)
{
case 0:
printf("emp_name : %s\n", emp_name);
continue;
case 1403: /* Not Found Data */
break;
default :
fprintf(stderr, "FETCH CSR ERROR %d",sqlca.sqlcode);
close_db();
exit(0);
}
}
- Altibase
EXEC SQL OPEN cur_emp;
if(sqlca.sqlcode != SQL_SUCCESS ) {
fprintf(stderr, "OPEN CSR ERROR %d\n",sqlca.sqlcode);
close_db();
exit(0);
}
for(;;)
{
EXEC SQL FETCH cur_emp INTO :emp_name, :job_title, :salary;
switch(sqlca.sqlcode)
{
case SQL_SUCCESS:
printf("emp_name : %s\n", emp_name);
continue;
case SQL_NO_DATA: /* Not Found Data */
break;
default :
fprintf(stderr, "FETCH CSR ERROR %d",sqlca.sqlcode);
close_db();
exit(0);
}
}
커서 Close#
커서 close문은 오라클 pro*C 와 Altibase Precompiler는 동일하다.
- 오라클
EXEC SQL CLOSE cur_emp;
- Altibase
EXEC SQL CLOSE cur_emp;
amic SQL문#
Altibase는 메소드1, 메소드2, 메소드3, 메소드4 형식을 지원한다.
오라클은 파라미터 마커(parameter marker)로서 “:v[1…n]”와 물음표(“?”)를 사용할 수 있다. Altibase는 물음표(“?”)만을 지원한다.
메소드 1#
- 오라클
char dynstmt1[80];
strcpy(dynstmt1, "DROP TABLE EMP" );
EXEC SQL EXECUTE IMMEDIATE :dynstmt1;
- Altibase
EXEC SQL BEGIN DECLARE SECTION;
char dynstmt1[80];
EXEC SQL END DECLARE SECTION;
strcpy(dynstmt1, "DROP TABLE EMP" );
EXEC SQL EXECUTE IMMEDIATE :dynstmt1;
메소드 2#
- 오라클
int emp_number;
char delete_stmt[120];
.
.
.
strcpy(delete_stmt, "DELETE FROM EMP WHERE EMPNO = :v1");
EXEC SQL PREPARE sql_stmt FROM :delete_stmt;
emp_number = 10;
EXEC SQL EXECUTE sql_stmt USING :emp_number;
- Altibase
EXEC SQL BEGIN DECLARE SECTION;
int emp_number;
char delete_stmt[120];
EXEC SQL END DECLARE SECTION;
.
.
.
strcpy(delete_stmt, "DELETE FROM EMP WHERE EMPNO = ?");
EXEC SQL PREPARE sql_stmt FROM :delete_stmt;
emp_number = 10;
EXEC SQL EXECUTE sql_stmt USING :emp_number;
메소드 3#
- 오라클
char sql_query[80];
int deptno = 10;
char ename[10];
strcpy(sql_query,"SELECT ename FROM emp WHERE deptno > :v1");
EXEC SQL PREPARE S FROM : sql_query;
EXEC SQL DECLARE C CURSOR FOR S;
EXEC SQL OPEN C USING :deptno;
for (;;)
{
EXEC SQL FETCH C INTO :ename;
.
.
.
}
- Altibase
EXEC SQL BEGIN DECLARE SECTION;
char sql_query[80];
int deptno = 10;
char ename[10];
EXEC SQL END DECLARE SECTION;
strcpy(sql_query,"SELECT ename FROM emp WHERE deptno > ? ");
EXEC SQL PREPARE S FROM : sql_query;
EXEC SQL DECLARE C CURSOR FOR S;
EXEC SQL OPEN C USING :deptno;
for (;;)
{
EXEC SQL FETCH C INTO :ename;
.
.
.
}
메소드 4#
- 오라클
#define MAX_COLUMN_SIZE 30
char name[10];
int number;
short ind_number;
char *sql_stmt = "INSERT INTO emp (empno, ename) VALUES(:e, :n);
SQLDA *binda;
.
.
.
binda = SQLSQLDAAlloc(SQL_SINGLE_RCTX, MAX_COLUMN_SIZE, 10, 10);
binda->N = MAX_COLUMN_SIZE;
EXEC SQL PREPARE stmt FROM :sql_stmt;
EXEC SQL DESCRIBE BIND VARIABLES FOR stmt INTO binda;
binda->N = binda->F;
binda->V[0] = (char*)&number;
binda->L[0] = (long)sizeof(int);
binda->T[0] = 3;
binda->I[0] = &ind_number;
binda->V[1] = (char*) name;
binda->L[1] = (long) 10;
binda->T[1] = 1;
binda->I[1] = (short*)0;
.
.
.
number = 1024;
strcpy(name, "ALLISON");
ind_number = 0;
EXECUTE stmt USING DESCRIPTOR binda;
- Altibase
#define MAX_COLUMN_SIZE 30
EXEC SQL BEGIN DECLARE SECTION;
char *sql_stmt = "INSERT INTO emp VALUES(?,?)";
SQLDA *binda;
EXEC SQL END DECLARE SECTION;
int number;
char name[10];
short ind_name;
binda = (SQLDA*) SQLSQLDAAlloc( MAX_COLUMN_SIZE );
EXEC SQL PREPARE stmt FROM :sql_stmt;
EXEC SQL DESCRIBE BIND VARIABLES FOR stmt INTO :binda;
binda->N = binda->F;
binda->V[0] = (char*)&number;
binda->L[0] = sizeof(int);
bidna->T[0] = SQLDA_TYPE_SINT;
binda->I[0] = NULL;
binda->V[1] = (char*)name;
binda->L[1] = 10;
binda->T[1] = SQLDA_TYPE_CHAR;
binda->I[1] = (short*)&ind_name;
number = 1024;
strcpy(name, "ALLISON");
ind_name = strlen(name);
EXEC SQL EXECUTE stmt USING DESCRIPTOR :binda;
수행 결과 및 상태 코드#
오라클과 Altibase의 실행 시간 에러 처리를 위한 SQLSTATE, SQLCODE, SQLCA 값의 차이점을 비교한다.
SQLCA#
내장 SQL문의 수행 결과를 저장하는 구조체이다. Altibase가 지원하는 구성 요소는 sqlcode, sqlerrm.sqlerrmc, sqlerrm.sqlerrml, sqlerrd[2]이며, 오라클의 SQLCA에만 존재하고 Altibase에서 지원하지 않는 sqlwarn 같은 구성 요소는 사용할 수 없다.
SQLCA의 선언#
- 오라클
EXEC SQL INCLUDE SQLCA;
또는
#include <sqlca.h>
- Altibase
별도의 선언 없이 사용할 수 있다.
sqlca.sqlcode 상태값#
- 오라클
| Status Code | Description |
|---|---|
| 0 | Success |
| >0 | No rows returned |
| \<0 | database, system, network , application error |
- Altibase
| Status Code | Description |
|---|---|
| SQL_SUCCESS | Success |
| SQL_SUCCESS_WITH_INFO | |
| SQL_NO_DATA | No rows returned |
| SQL_ERROR | |
| SQL_INVALID_HANDLE |
sqlca.sqlerrm#
오라클과 Altibase에서 sqlerrmc, sqlerrml은 용도와 사용법이 동일하다.
sqlca.sqlerrd[2]#
- 오라클
INSERT, UPDATE, DELETE 또는 SELECT 연산에 의해 영향 받은 레코드 개수로 이 값은 누적된다.
- Altibase
INSERT, UPDATE 또는 DELETE 연산에 의해 영향 받은 레코드 개수로 누적되지 않는다.
배열인 출력 호스트 변수를 사용하여 select 문이나 FETCH문 수행 시 반환되는 레코드 개수이다.
SQLSTATE#
SQLSTATE에는 상태 코드가 저장되며 이 상태 코드를 통해 에러와 예외 상황의 종류를 알 수 있다.
SQLSTATE의 선언과 사용#
- 오라클
SQLSTATE를 아래와 같이 선언하고, 전처리기의 명령행 옵션으로 MODE=ANSI를 명시해야 한다.
char SQLSTATE[6];
- Altibase
별도의 선언 없이 사용할 수 있다.
SQLSTATE의 상태 코드#
오라클과 Altibase의 SQLSTATE 상태 코드는 그 의미와 코드값이 다르므로, 8장의 상태 코드 테이블과 ODBC 코드 테이블을 참조하여 변환해야 한다.
SQLCODE#
SQLCODE에는 내장 SQL문 수행 후 에러 코드가 저장된다.
SQLCODE의 선언과 사용#
- 오라클
SQLCODE를 아래와 같이 선언하고, 전처리기의 명령행 옵션으로 MODE=ANSI를 명시해야 한다.
long SQLCODE;
- Altibase
별도의 선언 없이 사용할 수 있다.
Altibase에서의 SQLCODE의 자료형은 int 형이다.
SQLCODE의 상태코드값#
- 오라클
sqlca.sqlcode와 동일한 상태 코드 값이 저장된다. - Altibase
| 상태코드 | 설명 |
| 0 | 내장 SQL문을 성공적으로 수행한 경우. 즉, sqlca.sqlcode 값이 SQL_SUCCESS 인 경우 |
| 1 | 내장 SQL문을 수행하였으나 예외 상황이 발견된 경우. 즉, sqlca.sqlcode 값이 SQL_SUCCESS_WITH_INFO 인 경우 |
| 100 | SELECT문이나 FETCH문 수행 후 반환되는 레코드가 없는 경우. 즉, sqlca.sqlcode 값이 SQL_NO_DATA인 경우 |
| -1 | 내장 SQL문 수행 시 에러가 발생하였지만 해당 에러코드가 없는 경우. 이 때의 sqlca.sqlcode 값은 SQL_ERROR 이다. |
| -2 | 데이터베이스 서버와 연결하지 않고 내장 SQL문을 수행한 경우. 즉, sqlca.sqlcode 값이 SQL_INVALID_HANDLE 인 경우 |
| 위의 값 이외의 값이 SQLCODE에 설정되는 경우는 에러 메시지가 있는 경우로서 해당 SQL에서 에러가 발생한 경우이다. | |
기타 차이점#
Altibase와 오라클의 커밋 모드 변경 방법, 기본 커밋 모드, 커밋 방법의 차이점을 설명한다.
기본 커밋 모드#
| 오라클 | Altibase |
|---|---|
| Non-Autocommit mode | Autocommit mode |
커밋 모드 변경#
- 오라클
EXEC SQL ALTER SESSION SET AUTOCOMMIT = TRUE 또는 FALSE
EXEC SQL ALTER SESSION SET AUTOCOMMIT = TRUE 또는 FALSE
- Altibase
EXEC SQL AUTOCOMMIT ON
또는
EXEC SQL ALTER SESSION SET AUTOCOMMIT = TRUE 또는 FALSE
명시적 커밋#
- 오라클
EXEC SQL COMMIT;
또는
EXEC SQL COMMIT WORK;
- Altibase
EXEC SQL COMMIT;
예제 프로그램#
앞서 기술된 내용이 담긴 예제 프로그램이다.
오라클#
#include <stdio.h>
#include <stdlib.h>
EXEC SQL include sqlca.h;
EXEC SQL BEGIN DECLARE SECTION;
char emp_name[21];
char job_title[21];
int salary;
int emp_number;
EXEC SQL END DECLARE SECTION;
char uid[10] = "SCOTT";
char pwd[10] = "TIGER";
int main(void)
{
int dynamic_emp_number;
char dynamic_stmt[120];
EXEC SQL CONNECT :uid IDENTIFIED BY :pwd;
if ( sqlca.sqlcode != 0 ) {
fprintf(stderr, "DataBase Connect Error : [%d]!!!", sqlca.sqlcode);
exit(-1);
}
/* INSERT */
/* value setting */
emp_number = 10;
strcpy(emp_name, "oracle1");
strcpy(job_title, "oracle dba1");
salary = 10000;
/* INSERT DML */
EXEC SQL INSERT INTO emp (empno, ename, job, sal)
VALUES (:emp_number, :emp_name, :job_title, :salary);
if ( sqlca.sqlcode != 0 ) {
fprintf(stderr, "DataBase Connect Error : [%d]!!!", sqlca.sqlcode);
exit(-1);
}
emp_number = 20;
strcpy(emp_name, "oracle2");
strcpy(job_title, "oracle dba2");
salary = 10000;
EXEC SQL INSERT INTO emp (empno, ename, job, sal)
VALUES (:emp_number, :emp_name, :job_title, :salary);
if ( sqlca.sqlcode != 0 ) {
fprintf(stderr, "Insert Error : [%d]!!!", sqlca.sqlcode);
exit(-1);
}
/* SELECT DML */
emp_number = 10;
EXEC SQL SELECT ename, job, sal INTO :emp_name, :job_title, :salary
FROM emp
WHERE empno = :emp_number;
if ( sqlca.sqlcode != 0 ) {
fprintf(stderr, "Select Error : [%d]!!!", sqlca.sqlcode);
exit(-1);
}
printf(" SELECT result : ename=[%s], job=[%s], sal=[%d]\n",
emp_name, job_title, salary);
/* UPDATE DML */
emp_number = 10;
salary = 2000;
EXEC SQL UPDATE emp SET sal = :salary WHERE empno = :emp_number;
if ( sqlca.sqlcode != 0 ) {
fprintf(stderr, "Update Error : [%d]!!!", sqlca.sqlcode);
exit(-1);
}
/* Cursor Create */
EXEC SQL DECLARE cur_emp CURSOR FOR
SELECT ename, job, sal FROM emp;
/* Cursor Open */
EXEC SQL OPEN cur_emp;
if(sqlca.sqlcode != 0 ) {
fprintf(stderr, "OPEN CSR ERROR %d\n",sqlca.sqlcode);
exit(-1);
}
/* Fetch Cursor */
for(;;)
{
EXEC SQL FETCH cur_emp INTO :emp_name, :job_title, :salary;
switch(sqlca.sqlcode)
{
case 0:
printf("Fetch Result : emp_name[%s], job[%s], sal=[%d]\n",
emp_name, job_title, salary );
continue;
case 1403: /* Not Found Data */
break;
default :
fprintf(stderr, "FETCH CSR ERROR %d",sqlca.sqlcode);
exit(-1);
}
break;
}
/* Cursor Close */
EXEC SQL CLOSE cur_emp;
/* Dynamic SQL */
strcpy(dynamic_stmt, "DELETE FROM EMP WHERE EMPNO = :v1");
EXEC SQL PREPARE sql_stmt FROM :dynamic_stmt;
dynamic_emp_number = 10;
EXEC SQL EXECUTE sql_stmt USING :dynamic_emp_number;
/* Disconnect */
EXEC SQL COMMIT WORK RELEASE;
exit(0);
}
Altibase#
#include <stdio.h>
#include <stdlib.h>
EXEC SQL BEGIN DECLARE SECTION;
char emp_name[21];
char job_title[21];
int salary;
int emp_number;
char uid[10];
char pwd[10];
char dynamic_stmt[120];
int dynamic_emp_number;
EXEC SQL END DECLARE SECTION;
int main(void)
{
strcpy(uid, "SYS" );
strcpy(pwd, "MANAGER");
EXEC SQL CONNECT :uid IDENTIFIED BY :pwd;
if ( sqlca.sqlcode != SQL_SUCCESS ) {
fprintf(stderr, "DataBase Connect Error : [%d]!!!", sqlca.sqlcode);
exit(-1);
}
/* INSERT */
/* value setting */
emp_number = 10;
strcpy(emp_name, "altibase1");
strcpy(job_title, "dba1");
salary = 10000;
/* INSERT DML */
EXEC SQL INSERT INTO emp (empno, ename, job, sal)
VALUES (:emp_number, :emp_name, :job_title, :salary);
if ( sqlca.sqlcode != SQL_SUCCESS ) {
fprintf(stderr, "DataBase Connect Error : [%d]!!!", sqlca.sqlcode);
exit(-1);
}
emp_number = 20;
strcpy(emp_name, "altibase2");
strcpy(job_title, "dba2");
salary = 20000;
EXEC SQL INSERT INTO emp (empno, ename, job, sal)
VALUES (:emp_number, :emp_name, :job_title, :salary);
/* SELECT DML */
emp_number = 10;
EXEC SQL SELECT ename, job, sal INTO :emp_name, :job_title, :salary
FROM emp
WHERE empno = :emp_number;
if ( sqlca.sqlcode != SQL_SUCCESS ) {
fprintf(stderr, "Select Error : [%d]!!!", sqlca.sqlcode);
exit(-1);
}
printf(" SELECT result : ename=[%s], job=[%s], sal=[%d]\n",
emp_name, job_title, salary);
/* UPDATE DML */
emp_number = 10;
salary = 2000;
EXEC SQL UPDATE emp SET sal = :salary WHERE empno = :emp_number;
if ( sqlca.sqlcode != SQL_SUCCESS ) {
fprintf(stderr, "Update Error : [%d]!!!", sqlca.sqlcode);
exit(-1);
}
/* Cursor Create */
EXEC SQL DECLARE cur_emp CURSOR FOR
SELECT ename, job, sal FROM emp;
/* Cursor Open */
EXEC SQL OPEN cur_emp;
if(sqlca.sqlcode != SQL_SUCCESS ) {
fprintf(stderr, "OPEN CSR ERROR %d\n",sqlca.sqlcode);
exit(-1);
}
/* Fetch Cursor */
for(;;)
{
EXEC SQL FETCH cur_emp INTO :emp_name, :job_title, :salary;
switch(sqlca.sqlcode)
{
case SQL_SUCCESS:
printf("Fetch Result : emp_name[%s], job[%s], sal=[%d]\n",
emp_name, job_title, salary );
continue;
case SQL_NO_DATA: /* Not Found Data */
break;
default :
fprintf(stderr, "FETCH CSR ERROR %d %s\n",
sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
exit(-1);
}
break;
}
/* Cursor Close */
EXEC SQL CLOSE cur_emp;
/* Dynamic SQL */
strcpy(dynamic_stmt, "DELETE FROM EMP WHERE EMPNO = ?");
EXEC SQL PREPARE sql_stmt FROM :dynamic_stmt;
dynamic_emp_number = 10;
EXEC SQL EXECUTE sql_stmt USING :dynamic_emp_number;
/* Disconnect */
EXEC SQL DISCONNECT;
exit(0);
}