LoginSignup
0
0

More than 3 years have passed since last update.

C言語+ODBC で Db2 に接続してみた

Last updated at Posted at 2021-04-22

C言語からDb2へアクセスするには

C言語で作成するプログラムからDb2データベースを利用するには、以下2パターンあるようです。

  1. ODBC (このメモでこれから試そうとしている方法)
  2. 組み込みSQL ( ---> Link:「Db2で組み込みSQLのC言語アプリケーションを実行してみた」)

C言語+ODBCでデータベース接続する方法が知りたい

古くからある手法ですし、きっとしかるべき書物を紐解けば精緻な情報にたどり着けそうな基礎レベルの話のはずですが、案外Google検索しても情報がなかなか見つからないので、

  • ソースコード
  • コンパイル方法(必要なオプション)
  • 実行方法

など、整理してみようと思いました。

といってもC言語スキルはありませんので、こちらのサイトのサンプルコードを拝借して動かしてみます。
プログラミングの勉強をしよう@Wiki Windows-C > サンプル > DB2

上のサイトではWindows環境で実行されていますが、Windows10/Db2 11.5環境ではコンパイルがうまくいかなかったため、Linux環境でコンパイル/実行しました。

前提:

  • Cのコンパイラ(gcc)が導入されていること
  • Db2サーバ、Db2 ODBC Driverが導入されていること
  • Linux環境におけるDb2-ODBCアプリ接続のための事前構成が済んでいること
    ---> HOWTO: Setup ODBC application connectivity on Linux
    • この「HOWTO..」のTehnote、製品マニュアルに情報が整理されてない中で大変有難い存在ながら、見づらいし db2dsdriver.cfg ファイルのパスが間違ってるとか言いたいことは色々あります..
    • db2dsdriver.cfgファイルは「<odbcdriver_instroot>/cfg/db2dsdriver.cfg」に置いてください

環境:

  • Red Hat Enterprise Linux Server release 7.9 (Maipo)
  • gcc version 4.8.5 20150623 (Red Hat 4.8.5-44)
  • unixODBC-2.3.1-14.el7.x86_64
  • IBM Data Server Driver for ODBC and CLI (Linux/x86-64 64 bit) V11.5.5 Fix Pack 1
  • Db2 11.5.5.1

サンプルコード:

引用元:プログラミングの勉強をしよう@Wiki Windows-C > サンプル > DB2

db2_sample01.c
/* Standard C/C++ Headers */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* DB2 ODBC Header */
#include <sqlcli1.h>

int main(int argc, char** argv)
{
    /* Handles */   
    SQLHENV  henv = SQL_NULL_HENV;
    SQLHDBC  hdbc = SQL_NULL_HDBC;
    SQLHSTMT hstmt= SQL_NULL_HSTMT;

    /* Local variables */   
    SQLRETURN     rc;   
    SQLCHAR       statement[32761];
    SQLCHAR       mycolout[12];
    SQLINTEGER    mycoloutlen = 0;
    char          dbname[8 + 1];
    char          user[18 + 1];
    char          pswd[30 + 1];

    if (argc < 4) {       
        printf ("Usage: dbconn_ODBC_CLI <database name> <userid> <password>\n");
        exit (0);   
    }   
    strcpy (dbname, argv[1]);
    strcpy (user,   argv[2]);
    strcpy (pswd,   argv[3]);

    rc = SQLAllocHandle(SQL_HANDLE_ENV,
                        SQL_NULL_HANDLE,
                        &henv);   

    rc = SQLSetEnvAttr(henv
                     , SQL_ATTR_ODBC_VERSION
                     , (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);

    rc = SQLAllocHandle(SQL_HANDLE_DBC,
                        henv,
                        &hdbc);

    /* connect to the database */
    rc = SQLConnect(hdbc
                  , (SQLCHAR *)dbname
                  , SQL_NTS
                  , (SQLCHAR *)user
                  , SQL_NTS
                  , (SQLCHAR *)pswd
                  , SQL_NTS);
    printf ("\n  Successful connection to '%s' db using ODBC/CLI \n",dbname);

    rc = SQLAllocHandle(SQL_HANDLE_STMT,
                        hdbc,
                        &hstmt);

    strcpy(statement,"SELECT empno");
    strcat(statement,"  FROM DB2INST1.EMPLOYEE;");

    rc = SQLExecDirect(hstmt
                     , statement
                     , SQL_NTS);

    rc = SQLBindCol(hstmt
                  , 1
                  , SQL_C_CHAR
                  , mycolout
                  , sizeof(mycolout)
                  , &mycoloutlen);

    while((rc = SQLFetch(hstmt)) == SQL_SUCCESS
            || rc == SQL_SUCCESS_WITH_INFO){
        /* Print data */     
        printf("  Successful retrieval of record.  Column 'empno' has a value of '%s'\n",mycolout);
    }

    rc = SQLCloseCursor(hstmt);   
    rc = SQLFreeStmt(hstmt, SQL_RESET_PARAMS);
    rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
    rc = SQLDisconnect(hdbc);
    printf ("  Successful Disconnection from database '%s'\n",dbname);

    rc = SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
    rc = SQLFreeHandle(SQL_HANDLE_ENV, henv);
    printf ("  End of Program\n");
    return 0;

}

コンパイル:

# su - db2inst1
$ gcc -I"/database/config/db2inst1/sqllib/include" db2_sample01.c -o db2_sample01 -Wl,-rpath,/database/config/db2inst1/sqllib/lib64 -L/database/config/db2inst1/sqllib/lib64 -ldb2
[db2inst1@2a4bb38ac023 c]$ ls -ltr
total 106556
-rw-rw-r--. 1 db2inst1 db2iadm1 108615680 Apr 13 06:43 v11.5.5fp1_linuxx64_odbc_cli.tar
-rw-rw-r--. 1     1003     1004    471511 Apr 13 10:21 unixODBC-2.3.9-1.fc33.x86_64.rpm
-rw-r--r--. 1 db2inst1 db2iadm1      2567 Apr 13 11:14 db2_sample01.c
-rwxr-xr-x. 1 db2inst1 db2iadm1     13064 Apr 13 11:25 db2_sample01   ← 生成された

実行 ---> 成功!

コンパイルの結果生成された実行ファイル(db2_sample01) に引数を与えて実行すると、指定したDB/ユーザID/パスワードにてDb2に接続出来ることが確認できます。

$ ./db2_sample01 testdb db2inst1 cicdtest

  Successful connection to 'testdb' db using ODBC/CLI
  Successful Disconnection from database 'testdb'
  End of Program
$

Windows用に開発されたコードなのでLinuxでは動かない可能性もありましたが、運よく無事動きました。

備考:コンパイルエラー(オプション不足)

Db2 11.5 (64bit) にアクセスしたいCプログラムをコンパイルするには、このオプションが必須:
「-L/database/config/db2inst1/sqllib/lib64 -ldb2」

オプションを入れ忘れてコンパイルしようとすると、以下のようなエラーが出ます。

$ gcc -I"/database/config/db2inst1/sqllib/include" db2_sample01.c -o db2_sample01.exe
/tmp/cc6tx5sJ.o: In function `main':
db2_sample01.c:(.text+0xc7): undefined reference to `SQLAllocHandle'
db2_sample01.c:(.text+0xe4): undefined reference to `SQLSetEnvAttr'
db2_sample01.c:(.text+0xfb): undefined reference to `SQLAllocHandle'
db2_sample01.c:(.text+0x136): undefined reference to `SQLConnect'
db2_sample01.c:(.text+0x166): undefined reference to `SQLAllocHandle'
db2_sample01.c:(.text+0x200): undefined reference to `SQLExecDirect'
db2_sample01.c:(.text+0x232): undefined reference to `SQLBindCol'
db2_sample01.c:(.text+0x25b): undefined reference to `SQLFetch'
db2_sample01.c:(.text+0x277): undefined reference to `SQLCloseCursor'
db2_sample01.c:(.text+0x28a): undefined reference to `SQLFreeStmt'
db2_sample01.c:(.text+0x29d): undefined reference to `SQLFreeHandle'
db2_sample01.c:(.text+0x2ab): undefined reference to `SQLDisconnect'
db2_sample01.c:(.text+0x2d7): undefined reference to `SQLFreeHandle'
db2_sample01.c:(.text+0x2ea): undefined reference to `SQLFreeHandle'
collect2: error: ld returned 1 exit status

(以上です)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0