부록 B. Pro*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의 데이터 타입 변환 함수와 내장 함수를 설명한다.
오라클에서 사용되는 함수의 이름, 용도, 사용법이 유사하다.
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;
Dynamic 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
EXEC SQL ALTER SESSION SET AUTOCOMMIT = FALSE
-
Altibase
또는EXEC SQL AUTOCOMMIT ON
또는EXEC SQL ALTER SESSION SET AUTOCOMMIT = TRUE
EXEC SQL ALTER SESSION SET AUTOCOMMIT = 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);
}