ODBC드라이버를 이용한 2개 이상의 Statement 사용방법
.소개: 본 문서는 CUBRID 2008의 ODBC 드라이버와 Visual Studio에서 win API를 이용하여 하나의 Connection에서 두개 이상의 Statement를 사용하는 방법을 설명합니다.
2009-06-10 고객지원팀, 권성준CUBRID
적용 대상: CUBRID2008 R1.4(windows)
본 문서는 아래와 같은 환경에서 적용 되었습니다.
큐브리드 2008이상
window XP 와 Visual Studio 6.0 Enterprise
CUBRID 2008은 AutoCommit이 default 값으로 ON으로 되어 있습니다. 이 영향으로 하나의 Connection에서 여러 개의 Statement의 사용을 원하는 경우에, 하나의 Statement가 close되면 나머지 다른 Statement도 close가 됩니다. 이러한 현상을 미연에 방지하기 위한 방법으로 AutoCommit을 OFF로 설정하여 사용하는 방법을 소개합니다.
시작 -> 제어판 -> 관리도구 -> 데이터 원본(ODBC)
추가를 클릭
CUBRID Drive를 선택하고 마침을 클릭.
아래와 같이 값을 입력하고 OK를 클릭.
샘플 코드 작성
#include <stdio.h>
#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#include <sqltypes.h>
#define char_len 30
#define MAX 255
void prepare_test(SQLHDBC hOdbc);
int main(){
SQLHENV hEnv;
SQLHDBC hOdbc;
SQLCHAR sqlState[char_len], pMsg[MAX];
long state;
SQLINTEGER NativeError;
SQLSMALLINT BufferLength;
TCHAR *UserID= "dba";
TCHAR *UserPWD= "";
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv);
SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hOdbc);
state = SQLConnect(hOdbc,(SQLCHAR *)"CUBRID",SQL_NTS,(SQLCHAR *)UserID,SQL_NTS,(SQLCHAR *)UserPWD,SQL_NTS);
if ((state != SQL_SUCCESS) && (state != SQL_SUCCESS_WITH_INFO)){
printf("Error SQLConnect %ldn", state);
SQLGetDiagRec(SQL_HANDLE_DBC, hOdbc, 1, sqlState, &NativeError, pMsg, MAX, &BufferLength);
printf("%s (%d)n", pMsg, (int)NativeError);
SQLFreeHandle(SQL_HANDLE_DBC, &hOdbc);
SQLFreeHandle(SQL_HANDLE_ENV, &hEnv);
exit(1);
}
SQLSetConnectAttr(hOdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, SQL_IS_UINTEGER);
prepare_test(hOdbc);
SQLDisconnect(hOdbc);
SQLFreeHandle(SQL_HANDLE_DBC, &hOdbc);
SQLFreeHandle(SQL_HANDLE_ENV, &hEnv);
return 0;
}
void prepare_test(SQLHDBC hOdbc){
SQLHSTMT hStmt1, hStmt2, hStmt3;
SQLINTEGER NativeError;
TCHAR result1[char_len];
char *sql1 = "SELECT name FROM athlete WHERE nation_code = 'KOR'";
char *sql2 = "INSERT INTO test_class VALUES(?)";
char *sql3 = "CREATE CLASS test_class (test_col STRING)";
SQLAllocHandle(SQL_HANDLE_STMT, hOdbc, &hStmt1);
SQLAllocHandle(SQL_HANDLE_STMT, hOdbc, &hStmt2);
SQLAllocHandle(SQL_HANDLE_STMT, hOdbc, &hStmt3);
if(SQLExecDirect(hStmt3, (SQLCHAR *)sql3, SQL_NTS) != SQL_SUCCESS){
printf("Execute Error(%s).n", sql3);
exit(1);
}
SQLBindCol(hStmt1, 1, SQL_C_CHAR, result1, sizeof(result1), &NativeError);
if(SQLExecDirect(hStmt1, (SQLCHAR *)sql1, SQL_NTS) != SQL_SUCCESS){
printf("Execute Error(%s).n", sql1);
exit(1);
}
if(SQLPrepare(hStmt2, (SQLCHAR *)sql2, SQL_NTS) != SQL_SUCCESS){
printf("Prepare Error.n");
exit(1);
}
while (SQLFetch(hStmt1) != SQL_NO_DATA){
if(SQLBindParameter(hStmt2, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, char_len-1, 0, result1, 0, NULL) != SQL_SUCCESS){
printf("Biniding Error.n");
exit(1);
}
if(SQLExecute(hStmt2) != SQL_SUCCESS){
printf("Execute Error.n");
exit(1);
}
}
printf("실행 종료.n");
SQLEndTran(SQL_HANDLE_DBC, hOdbc, SQL_COMMIT);
SQLFreeStmt(hStmt1, SQL_CLOSE);
SQLFreeStmt(hStmt2, SQL_CLOSE);
SQLFreeHandle(SQL_HANDLE_STMT, &hStmt1);
SQLFreeHandle(SQL_HANDLE_STMT, &hStmt2);
}
소스코드 설명
ODBC 드라이버를 이용하여, 두 개 이상의 Statement를 사용하는 방법은 다음과 같습니다.
1. SQLConnect API를 이용하여 DB에 연결하여 Connection 생성.
(연결핸들과 DNS, UserID, UserPW가 필요하며, SQL_NTS는 NULL로 끝나는 문자열의 길이를 의미.)
2. SQLSetConnectAttr API를 통해 SQL_ATTR_AUTOCOMMIT의 값을 SQL_AUTOCOMMIT_OFF로 설정.
(연결핸들과 설정 속성, 속성의 포인터 값이 필요.)
3. SQLPrepare API와 SQLBindParameter을 이용한 prepare 작업 수행.(SQLExecute에만 해당)
(sql문의 핸들, 바인딩의 순서, 매개변수의 Input/Output 방식, 매개변수의 C 데이터 타입, 매개변수의 sql 데이터 타입, 바인딩 값의 크기, 데이터 타입에 따른 소수점 아래의 자리수, 매개변수의 포인터가 필요하다.)
4. SQLExecDirect 또는 SQLExecute API를 이용하여 질의 수행.
(sql문의 핸들, sql문이 필요.)
5. SQLEndTran을 이용하여 COMMIT 또는 ROLLBACK으로 Connection 종료.
(핸들의 타입, 연결핸들, SQL_COMMIT 또는 SQL_ROLLBACK 필요.)