S-JIS[2025-06-14] 変更履歴

ODBCメモ

ODBCのメモ。


概要

ODBC(Open Database Connectivity)は、DBMSにアクセスするためのインターフェース。
要するにC言語の関数群。

ODBCドライバーが提供されているDBMSであれば、ODBCを使ってそのDBにアクセスできる。

RDBだけでなく、例えばMS-ExcelもODBCドライバーが提供されているので、Excelファイルに対してSQLを実行することが出来る。

ODBCは主にWindowsで使われるが、UNIX/Linuxでも使用できるらしい。


ODBCでDBに接続する例。(C言語)

#include <stdio.h>
#include <stdlib.h>
#include <sql.h>
#include <sqlext.h>
int main(void) {
    SQLHENV hEnv = NULL;
    SQLHDBC hDbc = NULL;
    SQLRETURN ret;
    SQLCHAR connStrIn[] = "DRIVER={PostgreSQL Unicode};SERVER=localhost;PORT=5432;DATABASE=testdb;UID=user;PWD=password;";
    SQLCHAR connStrOut[1024];
    SQLSMALLINT connStrOutLen;

    // 環境ハンドルの確保
    ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv);
    if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
        fprintf(stderr, "Failed to allocate environment handle\n");
        return EXIT_FAILURE;
    }

    // ODBC バージョンの設定
    ret = SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
    if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
        fprintf(stderr, "Failed to set environment attribute\n");
        SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
        return EXIT_FAILURE;
    }

    // 接続ハンドルの確保
    ret = SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc);
    if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
        fprintf(stderr, "Failed to allocate connection handle\n");
        SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
        return EXIT_FAILURE;
    }

    // データベースへ接続
    ret = SQLDriverConnect(
        hDbc,
        NULL,
        connStrIn,
        SQL_NTS,
        connStrOut,
        sizeof(connStrOut),
        &connStrOutLen,
        SQL_DRIVER_NOPROMPT);
    if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
        printf("Connected successfully to PostgreSQL!\n");

        // ...ここにSQL実行などを記述...

        SQLDisconnect(hDbc);
    } else {
        fprintf(stderr, "Failed to connect to database.\n");

        // エラーメッセージの取得
        SQLCHAR sqlState[6], msg[SQL_MAX_MESSAGE_LENGTH];
        SQLINTEGER nativeError;
        SQLSMALLINT msgLen;
        SQLGetDiagRec(SQL_HANDLE_DBC, hDbc, 1, sqlState, &nativeError, msg, sizeof(msg), &msgLen);
        fprintf(stderr, "SQLState: %s\nError: %s\n", sqlState, msg);
    }

    // クリーンアップ
    SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
    SQLFreeHandle(SQL_HANDLE_ENV, hEnv);

    return EXIT_SUCCESS;
}

まず、SQLAllocHandle()を呼んで、hEnvのインスタンス(Environment、環境)を生成する。

次に、SQLSetEnvAttr()を呼んで、使用するODBCバージョンを指定する。
(ODBCのバージョンによって、呼び出せる関数が違ってくる)
(現在はODBC4や3.5、3.8もあるようだが、多いのはODBC3だと思う)

それから、hDbcインスタンス(DB Connection)をSQLAllocHandle()によって生成する。
(hDbcは、SQLDriverConnect()を呼ぶ際に使われる)

そして、ODBCドライバー名やDBへの接続情報を指定してSQLDriverConnect()を呼び出すことで、DBに接続する。
(接続情報は、ODBCドライバーによって異なる)
SQLDisconnect()でDBから切断する。

最後にSQLFreeHandle()を呼んで、hDbcやhEnvインスタンスを解放する。
なお、DBを切断しておかないと、SQLFreeHandle()がエラーになる。


ODBCの各関数は、戻り値としてSQLRETURN(16ビット符号付き整数)を返す。

SQL_SUCCESS(0)とSQL_SUCCESS_WITH_INFO(1)は成功。
それ以外はエラー。
(SQL_SUCCESS_WITH_INFOは、「処理としては成功しているが、付随するメッセージがある」ことを示している)

SQL_SUCCESS_WITH_INFOとエラーの場合、SQLGetDiagRec()を呼び出すことで、エラーコードやエラーメッセージを取得できる。

エラーメッセージは複数ある場合がある。
SQLGetDiagRec()の第3引数recNumberで、何番目のエラーメッセージを取得するかを指定する。
全部のエラーメッセージを取得しようと思ったら、recNumberを1から始めて1ずつ増やしながら、SQL_NO_DATA(100)が返ってくるまでSQLGetDiagRec()を呼ぶ。


技術メモへ戻る
メールの送信先:ひしだま