ODBC 드라이버 연결

ODBC 드라이버 연결 방법을 소개합니다. 이를 통해 타 DBMS를 사용할 수 있습니다.

ODBC 개념

ODBC(Open DataBase Connectivity)는 모든 DBMS에 독립적인 데이터베이스 애플리케이션을 작성하기 위한 API의 집합 으로 특정 DBMS 사용자가 ODBC 드라이버를 통해 다른 DBMS를 사용할 수 있게 합니다.

따라서 DBMS에 연결하기 위해 ODBC 드라이버 관리자를 호출하여 사용하려는 드라이버를 호출하고 그 드라이버는 SQL을 사용하여 DBMS와 교신합니다. 즉, ODBC는 사용자와 각 데이터베이스 엔진 사이를 연결해 사용자가 공통된 인터페이스로 각각의 다른 데이터베이스 엔 진에 접근하게 하여 원하는 데이터를 참조할 수 있도록 합니다.

[그림 1] ODBC 구조도

[그림 1] ODBC 구조도

Tibero ODBC

Tibero ODBC는 2.x, 3.x 버전을 모두 지원합니다.

단, ODBC 표준 61개 함수 중 아래 2개 함수를 지원하지 않으며 사용을 할 경우 not implemented 오류가 발생합니다.

함수
설명

SQLBrowseConnect

연결 문자열을 찾아내기 위해 iterative한 방법을 제공하는 API입니다.

SQLSetScrollOptions

3.x에서 SQLSetStmtAttr로 대체합니다.

ODBC 표준 관련 링크

API에 대한 관련 정보는 "ODBC Function Summary" 관련글을 참고합니다.

tbCLI

Tibero가 제공하는 Call Level Interface(CLI)로 사용자의 애플리케이션 프로그램과 Tibero간의 SQL 인터페이스 역할을 수행합니다.

tbCLI는 ODBC 및 X/Open Call Level Interface Standard를 기초로 개발되었으며 Tibero ODBC=tbCLI로 인식해도 무방합니다.


Tibero ODBC 설치 및 구성

본 절에서는 ODBC의 설치 파일과 드라이버 등록 및 연결하는 방법에 대해서 설명합니다. (Tibero 7 FS02 Windows 바이너리 기준)

기본적으로 32bit 클라이언트 OS 환경에서는 32bit ODBC 설치, 64bit 클라이언트 OS 환경에서는 64bit ODBC 설치 방법을 설명합니다.

ODBC 설치 파일

클라이언트 인스톨러나 ODBC 인스톨러의 경우 GUI 환경에서 설치 및 등록을 자동으로 진행할 수 있습니다. 만약, 수동으로 진 행하려면 Tibero 서버가 설치된 환경에서 설치하고자 하는 클라이언트 컴퓨터 환경에 맞게 설치 파일을 가져옵니다.

Windows 계열에서 Tibero 7 ODBC Driver를 설치할 때 사용자의 편의를 위해 Tibero에서는 Win32/Win64용 ODBC 드라이 버 설치 실행 파일(.exe)과 Win32/Win64용 ODBC 클라이언트 라이브러리 파일(.dll)을 제공하고 있습니다.

아래는 배포되는 바이너리 파일명입니다. (해당 파일은 Tibero 7 기준이며 다른 버전의 경우 exe 파일명이 일부 다를 수 있습니다.)

구분
바이너리 파일명

Windows 32bit

libtbcli.dll, libtbcli.lib, tbodbc_driver_installer_7_32.exe

Windows 64bit

libtbcli.dll, libtbcli.lib, tbodbc_driver_installer_7_64.exe

서버와 버전이 일치하는지 확인하기 위해 libtbcli.dll 파일에서 오른쪽 마우스 버튼을 클릭한 뒤 [속성] > [자세히]의 Product version을 확인합니다.

[그림 2] ODBC 버전 확인

[그림 2] ODBC 버전 확인

ODBC 드라이버 등록

ODBC 드라이버 등록 순서는 아래와 같습니다.

  1. Tibero ODBC의 bit 선택

Tibero ODBC의 32bit 또는 64bit 선택은 설치하는 클라이언트 OS 환경에 맞추기보다는 Tibero ODBC를 사용하는 실제 어플리케이션의 bit에 맞춥니다.

  1. 바이너리 복사

Tibero 버전에 따라 ODBC 바이너리를 복사하는 위치가 다릅니다. 버전에 맞게 ODBC 바이너리를 위치합니다.

Tibero 6이상은 임의의 위치로 가능합니다. 단, 드라이버를 등록할 경우 해당 경로로 지정이 필요합니다. (예 : c:\Tibero)

  1. 드라이버 등록

command 창을 열어 ODBC 바이너리가 위치한 곳으로 이동한 후 명령어를 실행합니다. 만약 Windows 7 이상일 경우command 창을 관리자 권한으로 실행합니다.

  • 등록 방법

tbodbc_driver_installer_7_xx.exe -i <driver path>
항목
설명

< driver path >

ODBC 바이너리 디렉터리입니다.

  • 등록 예

  C:\Tibero\tibero7\bin>tbodbc_driver_installer_7_64.exe -i 
TiberoODBC Driver is being installed to [ C:\Tibero\tibero7\bin\ ]
<Caution!!> If you changed the driver path, you should remove all Tibero DSNs and 
add them again.

Success to INSTALL Tibero 7 ODBC Driver

  1. 드라이버 등록 확인

[시작] > [제어판] > [관리도구] > [데이터 원본(ODBC)] > [드라이버]에서 Tibero 드라이버가 등록된 것을 확인합니다.

[그림 3] ODBC 등록 확인

[그림 3] ODBC 등록 확인

ODBC 연결

Tibero ODBC를 사용하는 애플리케이션에서 연결 문자열(Connection String)을 사용하는 방식과 ODBC 관리자에 DSN(Data Source Name)을 등록하는 방식에 대해 설명합니다.

연결 문자열을 사용하는 방식

ODBC 함수 중에서 SQLDriverConnect를 사용할 경우 아래와 같은 정보가 필요합니다.

실제 사용할 때는 한줄로 입력하며 Tibero 5에서 DB 항목의 경우는 DB NAME에 해당하는 정보를 입력합니다.

DRIVER={Tibero 7 ODBC Driver};SERVER=192.168.17.21;PORT=1111;DB=tibero;
UID=tibero;PWD=tmax;

DSN을 등록하는 방식

ODBC 함수 중에서 SQLConnect를 사용할 때 DSN 정보가 필요하므로 [제어판] > [관리도구] > [데이터 원본(ODBC)] > [시스 템 DSN]에 데이터소스를 추가합니다.

[그림 4] ODBC 데이터소스 추가

[그림 4] ODBC 데이터소스 추가

접속방법은 IP, PORT 방식 또는 SID 방식이 있습니다.

  • IP, PORT 방식을 이용한 접속 Tibero 클라이언트 또는 서버의 설치 없이 ODBC Driver를 등록한 이후에 바로 사용할 수 있습니다.

[그림 5] IP, PORT 방식

[그림 5] IP, PORT 방식

  • SID 방식을 이용한 접속 Tibero 클라이언트 또는 서버가 설치된 경우 사용할 수 있으며 클라이언트 설정 파일인 tbdsn.tbr 파일에 SID 이름이 등록되어 있어야 합니다.

[그림 6] SID 방식

[그림 6] SID 방식

[그림 7] tbdsn.tbr

[그림 7] tbdsn.tbr

DSN 등록 후 [Test] 버튼을 클릭하여 정상적으로 접속이 되는지 확인합니다. 만약 실패할 경우 Tibero 서버의 기동, 방화벽 차단, 접속 정보 등을 확인합니다.

[그림 8] ODBC 접속 테스트

[그림 8] ODBC 접속 테스트


ODBC Manager 설치

본 절에서는 UNIX 계열(Linux 포함)에서 iodbc 설치 및 연동하는 과정을 설명합니다. UNIX 계열의 경우, ODBC Manager가 존재하지 않으므로 iodbc 또는 UNIX ODBC를 별도로 설치해야 합니다.

아래는 ODBC Manager를 설치하는 과정에 대한 설명입니다. 각 과정에 대한 상세한 설명은 해당 절의 내용을 참고합니다.

Driver Manager 설치

(1) 다운로드

http:/ iodbc.org 에서 다운로드 후 설치를 원하는 서버에 업로드합니다.

아래는 libiodbc-3.52.16.tar.gz 소스파일을 다운받아 서버에 설치한 결과입니다. 만약, tar 옵션의 xvzf가 적용되지 않을경우 먼저 gunzip으로 압축을 해제한 후 tar -xvf 옵션으로 해제합니다.

$ tar -xvzf libiodbc-3.52.16.tar.gz 

$ ls -al libiodbc-3.52.16
합계 884
drwxrwxr-x 14 tibero7 tibero7   4096  5월  2 20:25 . 
drwx------ 22 tibero7 tibero7   4096  6월 29 16:08 ..
-rw-rw-r--  1 tibero7 tibero7    991  2월 17  2021 AUTHORS
-rw-rw-r--  1 tibero7 tibero7    729  5월  2 20:20 COPYING
-rw-rw-r--  1 tibero7 tibero7  81151  5월  2 20:20 ChangeLog
-rw-rw-r--  1 tibero7 tibero7   1481  2월 17  2021 IAFA-PACKAGE
-rw-rw-r--  1 tibero7 tibero7   9236  2월 17  2021 INSTALL
-rw-rw-r--  1 tibero7 tibero7    729  5월  2 20:20 LICENSE
-rw-rw-r--  1 tibero7 tibero7   1588  5월  2 20:20 LICENSE.BSD
-rw-rw-r--  1 tibero7 tibero7  25277  2월 17  2021 LICENSE.LGPL
-rw-rw-r--  1 tibero7 tibero7  11613  5월  2 20:20 Makefile.am
-rw-rw-r--  1 tibero7 tibero7  37645  5월  2 20:20 Makefile.in
-rw-rw-r--  1 tibero7 tibero7  19293  5월  2 20:20 NEWS
-rwxrwxr-x  1 tibero7 tibero7  11118  5월  2 20:20 PORT.OpenLink
-rw-rw-r--  1 tibero7 tibero7  17076  5월  2 20:20 README
-rw-rw-r--  1 tibero7 tibero7  13828  5월  2 20:20 README.md
-rw-rw-r--  1 tibero7 tibero7   3918  5월  2 20:20 README_GIT
-rw-rw-r--  1 tibero7 tibero7   4030  5월  2 20:20 README_GIT.md
-rw-rw-r--  1 tibero7 tibero7   6110  5월  2 20:20 README_MACOSX
-rw-rw-r--  1 tibero7 tibero7   6110  5월  2 20:20 README_MACOSX.md
-rw-rw-r--  1 tibero7 tibero7   3971  5월  2 20:20 acinclude.m4
-rw-rw-r--  1 tibero7 tibero7  44084  5월  2 20:20 aclocal.m4 
drwxrwxr-x  2 tibero7 tibero7   4096  5월  2 20:25 admin
-rwxrwxr-x  1 tibero7 tibero7   6045  5월  2 20:20 autogen.sh 
drwxrwxr-x  2 tibero7 tibero7     67  5월  2 20:25 bin 
-rwxrwxr-x  1 tibero7 tibero7 496554  5월  2 20:20 configure 
-rw-rw-r--  1 tibero7 tibero7  21726  5월  2 20:20 configure.ac
drwxrwxr-x  2 tibero7 tibero7   4096  5월  2 20:25 debian
drwxrwxr-x  4 tibero7 tibero7    186  5월  2 20:25 drvproxy
drwxrwxr-x  2 tibero7 tibero7     94  5월  2 20:25 etc
drwxrwxr-x  2 tibero7 tibero7    289  5월  2 20:25 include
drwxrwxr-x  3 tibero7 tibero7   4096  5월  2 20:25 iodbc
drwxrwxr-x  4 tibero7 tibero7    163  5월  2 20:25 iodbcadm
drwxrwxr-x  2 tibero7 tibero7   4096  5월  2 20:25 iodbcinst
drwxrwxr-x 11 tibero7 tibero7   4096  5월  2 20:25 mac
drwxrwxr-x  2 tibero7 tibero7    139  5월  2 20:25 man
drwxrwxr-x  2 tibero7 tibero7     86  5월  2 20:25 samples

(2) iodbc 설치

tar.gz 파일로 설치 진행 시 아래와 같은 기본적인 순서를 따릅니다.

설치 전 사전환경 점검에서 prefix를 설정하지 않으면 기본적으로 /usr/local 아래에 설치되므로 특정 디렉터리를 지정하여 설치하고, 컴파일 및 설치 작업을 다시 수행할 경우 make clean 이후에 진행합니다.

  • 사전환경점검 '$HOME/iodbc' 디렉터리에 설치 전, 사전환경점검을 합니다.

$ mkdir iodbc
$ cd libiodbc-3.52.7/

./configure --prefix=$HOME/iodbc --disable-gui
.
.
.
iODBC Driver Manager 3.52.16 configuration summary 
==================================================

Installation variables
layout                default
prefix                /home/tibero7/iodbc 
exec_prefix           ${prefix}

Installation paths
programs              ${exec_prefix}/bin 
include files         ${prefix}/include 
libraries             ${exec_prefix}/lib 
manual pages          ${datarootdir}/man

Configuration files
odbc.ini              /etc/odbc.ini 
odbcinst.ini          /etc/odbcinst.ini 
default FILEDSN path  /etc/ODBCDataSources

Extensions
ODBC Version          3 
GUI Extensions        false 
ThreadSafe            true 
Install libodbc.so    true

  • 컴파일 점검결과에 문제가 없으면 컴파일을 합니다.

make

  • 파일 설치 컴파일된 파일을 설치합니다.

make install

(3) 설치 확인

설치된 서버에 원하는 bit로 설치됐는지 확인합니다. 특정 OS에 따라 64bit 서버에 32bit로 설치되는 경우가 있으 므로 file 명령어를 이용하여 확인이 필요합니다.

만약, ODBC Manager가 64bit로 설치됐다면 내부적으로 사용하는 Tibero ODBC 역시 64bit여야 하며 재설치가 필요 할 경우 make clean 이후에 진행합니다.

$ cd $HOME/iodbc/bin
$ file iodbctest
iodbctest: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked 
(uses shared libs), for GNU/Linux 2.6.32, 
BuildID[sha1]=b292e7409d349220796e2a5e7649f05504b7c8e6, not stripped

profile 설정

profile 내에 아래와 같은 내용을 추가합니다. IODBC_HOME의 경우 iodbc를 설치한 위치로 설정합니다.

# iodbc setting
export IODBC_HOME=$HOME/iodbc
export LD_LIBRARY_PATH=$IODBC_HOME/lib:$LD_LIBRARY_PATH 
export PATH=$IODBC_HOME/bin:$PATH

ODBC 환경 파일 설정 및 확인

ODBC Driver Manager의 환경 파일에 Tibero ODBC Driver를 등록하는 방법입니다. 연결 테스트 전에 Tibero 클라이언트 또는 서버의 설치 및 관련 환경설정이 되어야 합니다.

  1. 환경 파일 위치 및 이름 설정

$HOME/.odbc.ini(개인 설정) 또는 /etc/odbc.ini(공통 설정)으로 설정 가능합니다.

(우선순위는 $HOME/.odbc.ini가 높습니다.)

ODBC 환경 파일 설정 방법

[ODBC Data Source]
Tibero7     = Tibero 7 ODBC Driver 
[ODBC]
Trace       = 1
TraceFile   = /tmp/odbc.trace 

[<ODBC Data Sources 세부설정>]
Driver      = /home/tibero7/client/lib/libtbodbc.so 
Description = Tibero7 ODBC Datasource
SID         = <tbdsn.tbr 파일에 설정한 alias 정보> 
User        = tibero
Password    = tmax

항목
설명

< ODBC Data Sources >

Datasource 이름으로, Oracle Gateway 설정 파일에 해당 내용이 들어갑니다.

< ODBC Data Sources 세부설정>

ODBC Data Sources에서 설정한 이름으로, 대소문자까지 일치해야 합니다.

Driver

ODBC Manager에서 로드하는 Tibero ODBC Driver 파일입니다. 해당 파일 존재 여부 및 권한에 대해서 확인이 필요합니다.

SID

Tibero 클라이언트 또는 서버의 tbdsn.tbr 파일에 설정한 Alias 정보입니다.

User

사용자를 의미합니다.

Password

사용자 패스워드를 의미합니다. 테스트 및 링크 생성의 경우 별도로 사용자를 가져가므로 큰 의미는 없습니다.

ODBC 환경 파일 설정 예

$ cat .odbc.ini
[ODBC Data Sources]
tibero7 = Tibero7 ODBC driver

[ODBC]
Trace = 1
TraceFile = /home/tibero7/iodbc/tmp/odbc.trace

[Tibero7]
Server = 192.168.17.21
Port = 11111 
Database = tibero
Driver = /home/tibero7/tibero7/client/lib/libtbodbc.so
Description = Tibero7 ODBC Datasource 
SID = tibero
User = tibero
Password = tmax

  1. 연결 테스트

'$IODBC_HOME/bin' 폴더에 있는 iodbctest를 이용하여 연결 테스트를 수행합니다. 테스트에 문제가 발생하는 경우 ODBC 환경 파일 이름 및 위치와 설정을 확인합니다.

아래는 iodbctest를 이용한 연결 테스트 설정 방법입니다.

iodbctest "DSN=<dsn>;UID=<user>;PWD=<pwd>"
항목
설명

DSN

ODBC 환경 파일에서 설정한 ODBC Datasources 이름입니다.

UID, PWD

테스트 할 접속 계정 및 패스워드입니다.

아래는 iodbctest를 이용한 연결 테스트 사용 예입니다.

$ iodbctest "DSN=Tibero7;UID=tibero;PWD=tmax" 
iODBC Demonstration program
This program shows an interactive SQL processor 
Driver Manager: 03.52.1623.0502
Driver: 07.00.0218 (libtbodbc.so)

SQL>select * from lim_test;

C1
-------------------------------
100

result set 1 returned 1 rows.


문제 해결

본 절에서는 특정 문제가 발생했을 때 해결하는 방법을 설명합니다.

로그 발생

Tibero ODBC(=tbCLI)에서는 특정 환경변수를 적용하여 로그를 발생시키거나 글자 깨짐 등의 문제를 해결할 수 있습니다. 로그를 발생하는 환경변수의 경우 일부 성능이 느려질 수 있으므로 문제가 있을 때 일시적으로만 사용합니다.

아래는 자주 사용하는 환경변수에 대한 설명입니다.

환경변수명
설명

TBCLI_LOG_LVL

로그를 출력하게 하는 환경변수입니다. trace 값을 설정하면 로그가 출력됩니다.

TBCLI_LOG_DIR

로그를 생성하는 디렉터리를 설정합니다. 설정하지 않을 경우 아래와 같은 경로에 로그가 생성됩니다. (UNIX 계열 : /tmp/tbcli_날짜시간.log)

TB_NLS_LANG

클라이언트의 캐릭터 셋을 설정하는 부분으로 기본은 MSWIN949(한글)로 설정되어 있습니다. 보통은 DB 캐 릭터 셋과 일치시키거나 부분집합으로 설정하며 설정할 수 있는 값은 DB 캐릭터 셋과 동일합니다.

다른 환경변수에 대해서는 제품 매뉴얼 "Tibero 관리자 안내서""클라이언트 환경변수"를 참고합니다.


예제

본 절에서는 ODBC를 이용하여 연결하는 기본적인 형태의 예제와 특수한 타입의 예제를 설명합니다.

연결 예제

include <windows.h>
include <stdio.h>
include <stdlib.h>
include <sql.h>
include <sqlext.h>

/* #include "stdafx.h" */ 
define ROWSET_SIZE 20 
define DIRECT
int main(int argc, char* argv[])

{

   SQLRETURN rc = SQL_SUCCESS;
   SQLUINTEGER len;
   SQLHANDLE henv, hdbc, hstmt;
   SQLCHAR *sql = (SQLCHAR *)"SELECT TO_CHAR(SYSDATE,'YYYYMMDD') FROM DUAL";
   char buf[128]; 

/* Env Handle */

   SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
   SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
   SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);

/* Tibero Connect */

ifdef DIRECT 

// IP, PORT

rc = SQLDriverConnect(hdbc, 

   (SQLHWND)NULL,
   //(SQLCHAR *) "DRIVER={Tibero 4 ODBC Driver};\
                  SERVER=192.168.70.185;PORT=9629;UID=tibero;PWD=tmax;",
   (SQLCHAR *) "DRIVER={Tibero 5 ODBC Driver};\
       SERVER=192.168.70.185;PORT=9629;DB=t5;UID=dbtech;PWD=dbtech;", 
   SQL_NTS,
   NULL, 
   0, 
   NULL,
   SQL_DRIVER_NOPROMPT);

else

// Data Source Name 

rc = SQLConnect(hdbc,
 
                   (SQLCHAR *)"t5", SQL_NTS, /* Data Source Name or DB NAME */ 
                   (SQLCHAR *)"dbtech", SQL_NTS, /* User */
                   (SQLCHAR *)"dbtech", SQL_NTS); /* Password */
                   
endif
if (rc != SQL_SUCCESS) {
   fprintfstderr, "Connection failed!!!");
   exit(1); 
}
/* Statements Handle */
    SQLAllocHandle(SQL_HANDLE_TMT, hdbc, &hstmt); 
    printf("Query: %s\n", sql);
/* Execute Query */
    rc = SQLExecDirect(hstm, sql, SQL_NTS); 
    if (rc != SQL_SUCCESS) {
fprintf(stderr, "SQLExecDirect failed!!!"); 
    exit(1);
   }
/* Bind Result */
    SQLBindCol(hstmt, 1, SQL_C_CHAR, (SQLCHAR *)buf, 128, (long *)&len); 
    printf("Result: ", buf);
/* Fetch Result */
   while(SQLFetch(hstmt) != SQL_NO_DATA) { 
    printf("%s\n", buf);
   }
/* Release Handle and Close Connection */
SQLFreeStmt(hstmt, SQL_DROP);
SQLDisconnect(hdbc);
SQLFreeConnect(hdbc);
SQLFreeEnv(henv); 
return 0;
}

UNIX 계열에서 테스트 하는 경우, Tibero 클라이언트 또는 서버가 설치된 환경에서 위의 샘플 소스를 사용하여 아래와 같이 삭제, 추가, 컴파일 및 링크합니다.

아래는 Linux 64bit일 때 예제입니다.

  • 삭제

include <windows.h> 
include <sql.h> 
include <sqlext.h>

  • 추가

include <sqlcli.h>

  • 컴파일 및 링크

cc -m64 -O -ITB_HOME/client/include -LTB_HOME/client/lib -c test.c
cc -m64 -O -ITB_HOME/client/include -o test.bin -LTB_HOME/client/lib -ltbcli \
-lclialloc test.o
-rw-r--r--   1 tibero7 tibero7     5040 6월 29 17:03 test.c 
-rw-rw-r--   1 tibero7 tibero7     3352 6월 29 17:03 test.o

컴파일 및 링크 옵션의 경우 OS에 따라 일부 다를 수 있습니다.

Autocommit 예제

ODBC의 Autocommit 관련 기본설정은 ON 입니다. 애플리케이션에서 OFF로 처리하기 위해서는 아래와 같이 처리합니다.

include <windows.h>
include <stdlib.h>
include <stdio.h>
include <string.h>
include <sql.h>
include <sqlext.h> 
//#include<sqlcli.h>

int main() 
{
   SQLRETURN rc;
SQLHANDLE henv, hdbc, hstmt;
   SQLCHAR sRegNo[10], sRegName[25];
   SQLINTEGER sqlnts=SQL_NTS;

/* Env Handle */
   SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&henv);
   SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(void*)SQL_OV_ODBC3,0);
   SQLAllocHandle(SQL_HANDLE_DBC,henv,&hdbc);

// Set Connection Attribute
   //SQLSetConnectAttr(hdbc,5,(void*)SQL_LOGIN_TIMEOUT,0); 

/* Tibero Connect */

rc = SQLConnect(hdbc,

               (SQLCHAR *)"t5", SQL_NTS, /* Data Source Name or DB NAME */ 
               (SQLCHAR *)"dbtech", SQL_NTS, /* User */
               (SQLCHAR *)"dbtech", SQL_NTS); /* Password */

if (rc != SQL_SUCCESS) {
    printf("Connection failed!!! : %d", rc);
        exit(1); 
    }

/* Set AutoCommit ON/OFF */
rc = SQLSetConnectAttr(hdbc,SQL_ATTR_AUTOCOMMIT,(SQLPOINTER)SQL_AUTOCOMMIT_OFF, 0); 

//rc = SQLSetConnectAttr(hdbc,SQL_ATTR_AUTOCOMMIT,(SQLPOINTER)SQL_AUTOCOMMIT_ON, 0);
   if (rc != 0) return NULL; 
   /* Statements Handle */
   SQLAllocHandle(SQL_HANDLE_STMT,hdbc,&hstmt);

/* Execute Query - INSERT */
rc = SQLExecDirect(hstmt,(SQLCHAR *)"INSERT INTO reg VALUES(100,'Seoul')",SQL_NTS); 
    if (rc != SQL_SUCCESS) {
        printf("Insert Failed!!!"); 
        exit(1);
    }

/* Commit */
// rc = SQLEndTran(SQL_HANDLE_DBC, hdbc, SQL_COMMIT); 

    /* Execute Query - SELECT */
    rc = SQLExecDirect(hstmt,(SQLCHAR*)"SELECT * FROM reg",SQL_NTS); 
    if (rc != SQL_SUCCESS) {

printf(stderr, "Select Failed!!!"); 
    exit(1);
    }

// Fetch
printf("%10s%25s\n","REGNO","REGNAME");
printf("%10s%25s\n","=====","========================"); 
while( SQLFetch(hstmt) != SQL_NO_DATA ) {
  SQLGetData(hstmt,1,SQL_C_CHAR,sRegNo,10,&sqlnts); 
  SQLGetData(hstmt,2,SQL_C_CHAR,sRegName,25,&sqlnts); 
  printf("%10s%25s\n", sRegNo,sRegName);
} // while end
printf("%10s%25s\n","=====","========================"); 
/* Release Handle and Close Connection */
SQLFreeStmt(hstmt, SQL_DROP);
SQLDisconnect(hdbc);
SQLFreeConnect(hdbc);
SQLFreeEnv(henv);
  return 0;
}

타입 관련 예제

아래는 CLOB을 이용한 특수한 타입의 예제입니다.

// gcc test_clob.c -ITB_HOME/client/include -L$TB_HOME/client/lib -ltbcli 
// a.out DSN USERNAME PASSWORD

include <stdio.h>
include <assert.h>
include "sqlcli.h"
SQLRETURN _rc = SQL_SUCCESS;
SQLHANDLE _henv = SQL_NULL_HANDLE;
SQLHANDLE _hdbc = SQL_NULL_HANDLE;
SQLHANDLE _hstmt = SQL_NULL_HANDLE;
SQLCHAR *DSN = NULL;
SQLCHAR *UID = NULL;
SQLCHAR *PWD = NULL;
int
main(int argc, char **argv)

{
 SQLINTEGER lob_loc = 0;
 SQLLEN ind = 0;
 SQLLEN lob_ind = 0;
 SQLINTEGER byte_len = 0;
 SQLBIGINT lob_len = 0;
 SQLCHAR lob_char[10+1]; // 버퍼크기(10)+널텀(1)
 
 // 읽어들일 글자 수,버퍼크기가 10이므로 5로 설정 
 SQLINTEGER read_char_len = 5;
 SQLINTEGER sqlnts=SQL_NTS;

 int offset = 1; // 여러번 나누어 가져올때의 offset 
 int lob_length;

 rc = SQLAllocEnv(&henv);
 rc = SQLAllocConnect(henv, &_hdbc); 
 DSN = (SQLCHAR *)argv[1];
 UID = (SQLCHAR *)argv[2]; 
 PWD = (SQLCHAR *)argv[3];

 rc = SQLConnect(hdbc, DSN, SQL_NTS, UID, SQL_NTS, PWD, SQL_NTS); 
 rc = SQLAllocStmt(hdbc, &_hstmt);
 rc = SQLExecDirect(hstmt, (SQLCHAR *)"DROP TABLE T", SQL_NTS);
 rc = SQLExecDirect(hstmt, (SQLCHAR *)"CREATE TABLE T(C1 CLOB)", SQL_NTS); 
 rc = SQLExecDirect(hstmt, (SQLCHAR *)"DELETE FROM T", SQL_NTS);
 rc = SQLExecDirect(hstmt, (SQLCHAR *)"INSERT INTO T VALUES (NULL)",
                    SQL_NTS);

_rc = SQLEndTran(SQL_HANDLE_DBC, _hdbc, SQL_COMMIT); 

rc = SQLFreeStmt(hstmt, SQL_RESET_PARAMS);

/* Case 1 */

rc = SQLExecDirect(hstmt, (SQLCHAR *)"SELECT * FROM T", SQL_NTS); 

rc = SQLFetch(hstmt);

/* must be return SQL_SUCCESS with SQL_NULL_DATA indicator value

- at first invocation */
  rc = SQLGetData(hstmt, 1, SQL_C_CHAR, NULL, 0, &ind);

/* c1컬럼(clob)이 null인지 확인. null이면 indicator가 SQL_NULL_DATA */
  
if (ind == SQL_NULL_DATA) {

   printf("CASE1: lob : null\n"); 
}

/* must be return SQL_NO_DATA at second invocation*/ 

rc = SQLGetData(hstmt, 1, SQL_C_CHAR, NULL, 0, &ind);
assert(_rc == SQL_NO_DATA);
rc = SQLCloseCursor(hstmt);
rc = SQLFreeStmt(hstmt, SQL_DROP); 
/* Case 2 : lob locator사용 */ 
ind = 0;
rc = SQLAllocStmt(hdbc, &_hstmt);
rc = SQLExecDirect(hstmt, (SQLCHAR *)"DELETE FROM T", SQL_NTS); 
rc = SQLExecDirect(hstmt, (SQLCHAR *)"INSERT INTO T \
VALUES ('티맥스소프트abc티베로입니다.')", SQL_NTS);
rc = SQLExecDirect(hstmt, (SQLCHAR *)"SELECT * FROM T", SQL_NTS); 
rc = SQLBindCol(hstmt, 1, SQL_C_CLOB_LOCATOR, \
                          (SQLPOINTER)&lob_loc, 0, &ind);
rc = SQLFetch(hstmt); // c1이 null이 아니면 lob_loc이 여기서 채워짐 
/* 해당 lob 데이터가 NULL인지 확인 */
if (ind == SQL_NULL_DATA) {
  printf("CASE2 : lob : null\n");
} 
else {

   rc = SQLLobGetLength(hstmt, lob_loc, &lob_len, NULL); 
   printf("CASE2(lob_len) : lob len : %lld\n", lob_len);
/*

SQLRETURN SQL_API

SQLLobGetData2(SQLHSTMT StatementHandle,

       SQLINTEGER Locator,

// 1부터 시작, 문자 수 의미의 offset, 여러번 호출 시 값 변경 필요
        SQLBIGINT Offset,
        SQLINTEGER *ReadLength, // 읽어들일 문자 수
        SQLSMALLINT TargetCType,
        SQLPOINTER DataPtr,
        SQLINTEGER BufferLength, // 버퍼크기
        SQLLEN *Indicator)
*/

while (1) {
      if( read_char_len > lob_len )
              read_char_len = lob_len;
              
      rc = SQLLobGetData2(hstmt, lob_loc, offset, &read_char_len \ 
      , SQL_C_CHAR,lob_char, sizeof(lob_char),&lob_ind);
      if (!SQL_SUCCEEDED(_rc) || lob_ind <= 0)
          break;
      offset += read_char_len; 
      lob_len -= read_char_len;
      printf("length of writing buffer : %lld\n", lob_ind); 
      printf("lob data : %s\n", lob_char);
   }// while end 
 }

 //rc = SQLExecDirect(hstmt, (SQLCHAR *)"DROP TABLE T", SQL_NTS); 
 rc = SQLDisconnect(hdbc);
 rc = SQLFreeConnect(hdbc); 
 rc = SQLFreeEnv(henv); 
 return 0;
}

Last updated