気の向くままに辿るIT/ICT/IoT
SQL用API

ODBC/Open DataBase Connectivity オープンデータベースコネクティビティ

ホーム前へ次へ
ODBC Open DataBase Connectivity オープンデータベースコネクティビティとは?

ODBC/Open DataBase Connectivity

ODBCとは

 ODBCとは、Open DataBase Connectivityの略で1992年Microsoft社が提唱し、後に広く無償で公開された広義のDBSQLをサポートしたRDB・リレーショナルデータベースに接続する為の標準技術・規格となったC言語ベースのAPI/Application Program Interface(Application Programming Interface)です。

 ODBCからJava用APIとして派生したものにJDBCがあります。

広義のDBに対応するODBC

 尚、ODBCでは、RDBだけでなくExcelをはじめとする表計算ソフトやテキストファイル、電子メールデータ等々、広義のデータベースに接続することができます。

DB接続技術ODBCはプラットフォーム非依存の世界標準

 ODBCは、1995年The Open GroupによってSQL/CLIとして標準化され、ODBCは、この標準化されたCLIをベースとした技術という位置づけになっており、環境(実装、処理系)に依存しないデータベースアクセス技術として国際標準となっています。

 このSQL/CLIのCLIは、CLI/Call Level Interface(呼び出しレベルインタフェース≒呼び出して使うインタフェース≒埋め込みではないインタフェース≒動的インタフェース)ですが、同様にCLIと呼ばれるものに、やはり同社の.NET Frameworkのベースとなる技術としても公開されている世界標準CLI/Common Language Infrastructure(共通言語基盤)がありますが、これらは全く異なるもので「C++/CLI」は、「Standard ECMA-372(1st Edition:2005/12)」として標準化団体Ecma Internationalによって標準化されています。

ミドルウェアとしてのDB/RDB接続技術

 ウェブシステムやクライアントサーバーシステム上では、一般にデータベースはサーバ上にあり、ネットワークを介してアクセスしますが、ISAM/Indexed Sequential Access Method(索引付き順次アクセスメソッド)を採用した、いわゆるOracle、SQL Server、PostgreSQL、MySQL等々のRDBMSにアクセスする際にはSQLを利用します。

 その際、SQLをサポートしない一般的なプログラミング言語とRDBMSを仲介する「標準的な専用のミドルウェア」という技術領域を確立したのもODBC(SQL/CLI)であると言ってもいいでしょう。

 様々なプログラム言語が様々なDB/RDBに接続する事ができるのは橋渡しをしてくれるこれら複数のRDB対応のODBC等の規格が存在するからとも言えますし、そもそも各プログラム言語がそれぞれにRDBに接続する為に機能を実装することは現実的ではありません。

 なぜなら標準的な規格がない場合、RDBに仕様の変更や追加があった場合を想定すると各プログラム言語において対応しなければならなくなりますし、プログラム言語が実装する事自体プログラムが重くなる一因となりますが、標準の規格があれば、その基準に合わせ、影響のでないように仕様変更・拡張を検討する事もできますし、対応ができるからです。

 但し、プログラミング言語やスクリプト言語、RDBMSの違いがODBC(SQL/CLI)の拡張としての派生という形で存在する為、やや仕方ない感もあるものの、それを勘案しても若干標準化の有用性が削がれている感は否めません。

 尚、Perlから利用できるデータベース接続インタフェースの1つにDBD/DBIがあり、DBDは各RDBへの専用インタフェースを含むモジュールで、その汎用(共通)インタフェースがDBIで、Oracle/SQL Server/MySQL/PostgreSQL...etc.に利用できます。

ODBCの実装

 ODBCは、CベースのAPIでUNIX/Linux Cまたは、VC(VCを包含するVC++)やC++/VC++によって以下の例のように汎用ODBCドライバを一から書くこともできますし、別途、比較的簡単なMFCを利用する方法もあります。

#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#include <string.h>
#include <iostream.h>

#define LEN_COL1 xx
#define LEN_COL2 xx
...

int main(int argc, char* argv[ ])
{
HENV hEnv;
HDBC hDbc;
HSTMT hStmt;
RETCODE ret;
SQLCHAR CompliteConnect[255];
SWORD len;

  ret = SQLAllocEnv(&hEnv);
  ret = SQLAllocConnect(hEnv,&hDbc);
  ret = SQLAllocStmt(hDbc,&hStmt);

  SQLCHAR str_a[LEN_COL1],str_a[LEN_COL2]...;
  SQLINTEGER var1,var2...,actual_size1,actual_size2,actual_size3;

  rc = SQLExecDirect(hStmt,(unsigned char*)"SELECT * FROM foo",SQL_NTS);

  while (TRUE)
  {
    ret = SQLFetch(hStmt);
    if ( ret == SQL_NO_DATA )
      break;
    if ( ret == SQL_ERROR )
      break;
    SQLGetData(hStmt,1,SQL_C_DATATYPE,str_a,length,&actual_size1);
    SQLGetData(hStmt,2,SQL_C_DATATYPE,var1,length,&actual_size2);
    SQLGetData(hStmt,3,SQL_C_DATATYPE,var2,length,&actual_size3);
    ...
    cerr << ... << endl;
  }

  ret = SQLEndTran(SQL_HANDLE_ENV,henv,SQL_COMMIT);
  ret = SQLFreeStmt(hStmt,SQL_DROP);
  ret = SQLDisConnect(hDbc);
  ret = SQLFreeConnect(hDbc);
  ret = SQLFreeEnv(hEnv);

  return 0;
}
 sql.h/sqlext.hは、ほとんどの場合、別途用意する必要があると思います。 
 HENV/環境ハンドル、HDBC/DB接続ハンドル、HSTMT/接続文字列ハンドル
 RETCODE/戻り値、SQLCHAR/SQL文字列、SWORD/出力文字列のサイズの型
 SQLAllocEnv()メソッド:環境ハンドル取得 
 SQLAllocConnect()メソッド:DB接続ハンドル取得 
 SQLDriverConnect()メソッド:DB接続 
 SQLAllocStmt()メソッド:SELECT取得結果領域確保 
 SQLDriverConnect()/SQLExecDirect()メソッドの[SQL_NTS]は 
 実際のデータ長を省略する際のマクロ値でデータサイズとしての引数
 C/C++では文字列の末尾に\0を含める必要があるので省略できると便利

 SQLGetData()メソッド 

 【第1引数】hStmt:必須

 HandleSTateMenT/ステートメントハンドル 

 【第2引数】(col_num):必須 

 テーブル上のカラム(列)番号 

 【第3引数】SQL_C_DATATYPE:必須 

 ANSIまたはUnicodeにおけるCのデータ型:ODBC C Data Types参照 

 SQL_C_CHAR/SQL_C_VARCHAR/SQL_C_NUMERIC/SQL_C_FLOAT...etc. 

 【第4引数】(var):必須 

 データを格納するポインタ変数 

 【第5引数】length:必須 

 データ長(バッファサイズ)

 【第6引数】actual_size:必須

 データ長(実際のバイト数) 

 尚、SQLGetData()ではなく、SQLBindCol()メソッドで予め変数と列データを結びつけ(バインドし)ておくこともできます。 

 SQLBindCol()メソッドは、SQLGetData()メソッドと全く同じ書式、引数で記述することができ、メソッド名と記述する場所だけが異なります。 

 つまり、SQLBindCol()メソッドは、SQLExecDirect()メソッドによるSELECT文発行の直後からSQLFetch()メソッドを伴うwhileループより前にSQLGetData()メソッドと同じ書式で記述します。 

 cerr << ... << endl; 
 cerr:C++の標準エラー出力ストリーム
 endl:C++の改行付きバッファフラッシュ(一斉書き出し)命令
 SQLEndTran()メソッド:トランザクションの終了 
 SQLFreeStmt()メソッド:ステートメントハンドルのメモリ開放
 SQLDisConnect()メソッド:DB接続の切断
 SQLFreeConnect()メソッド:DB接続ハンドルのメモリ開放
 SQLFreeEnv()メソッド:SQL環境ハンドルのメモリ開放

ホーム前へ次へ