今さら学ぶ ODBC の基礎

データベースに関わって生きていく中で、どなた様もきっといつかどこかで触れることになるもの、ODBC(Open Database Connectivity)。
これまで「なんとなく使ったことがある」程度しか接点のなかったODBCについて、Microsoft社のドキュメントを読みながら、

 - ODBCについて理解するにはどの資料を読むのが良いか
 - ODBCとは何か
 - ODBC API を使ってデータベースにアクセスするには

を、できるだけ簡潔に整理していきたいと思います。


## ODBC関連の読み物

ここから先は、この資料を読んで理解した内容を、サマリーしていきます。

[Microsoft Open Database Connectivity (ODBC)  > ODBC プログラマー リファレンス > ODBC とは](
https://docs.microsoft.com/ja-jp/sql/odbc/reference/what-is-odbc?view=sql-server-ver15)

日本語で詳しく解説されていて、ありがたい！
概念の理解には、ひとまずこれを読んでおけばいいのではと感じました。

(じゃあなんでこのメモを起こしているのか？というと、正式な仕様書なだけに情報量が多いからです)

## ODBCとは

「ODBC」は、Microsoft社が決めた、「アプリケーションからデータベースにアクセスするための仕組み(仕様/ルール)」です。

例えば「`SQLConnect`という関数をプログラムのソースコードに記述するとデータベースに接続できる」といったように


 - プログラムのソースコードに何を記述すればよいか
 - 記述した関数が呼び出された場合に、DBMSとのインタラクションはどうなるのか

が規定されています。

「ODBCドライバー」は、ほとんどのデータベースにおいて無償提供されているライブラリーセットのことで、各種アプリケーションからデータベースに接続したり、データを取得するなどの機能を提供してくれるものです。
Db2につなぐにはDb2付属のODBCドライバー、OracleにつなぐためにはOracle付属のODBCドライバーを使います。

「ODBC」という仕様に沿って作られた「ODBCドライバー」がさまざまなRDBに対して存在していて、「ODBC」を利用した同じプログラムからは、（ドライバーを入れ変えることで）さまざまなRDBにアクセスすることができます。

もっと言うと、実のところODBCはDBアクセスに特化した技術ではなく、ファイルアクセスにも利用できたりするようですが、ここではDBアクセス用途に絞って見ていきます。

※ ひとりごと(余談): マイクロソフトが作った仕様というなら SQL Server専用の仕様？という疑問にも至りますがそういうわけではなく、ODBCという仕様に沿って作られたODBCドライバーを使えば、同じ文法で書いたプログラムから、どのRDBにアクセス出来るという便利なもの。

#### ODBCの特徴

いろいろありますが、あえて3つに絞って。

 - ODBC はデータベース API の仕様
 - ODBC API は、特定の DBMS またはオペレーティングシステムから独立しているもの
 - ODBC API は言語に依存しない

ODBC API を使えば、どの言語からでも、どのデータベース(DBMS)に対しても接続ができるということですね。

__補足__：
Javaの場合、Javaアプリケーションからデータベースを操作するAPIの仕様であるJDBCを利用します。JDBCドライバーとODBCドライバーは別物(別モジュール)で、提供されるAPIも異なります。


#### ODBCが提供されるようになった背景

さまざまなDBMSに対して、同じプログラムからデータアクセスを行いたいニーズに対して登場した技術(仕様)です。
ODBCでは各DBMSベンダーが提供するODBCドライバーが、DBアクセスロジックを隠蔽してくれているために、アプリケーション開発者はDBMSの種類を意識せず(＝DBMS固有のコードを書く必要なく)、同じ ODBC API を呼び出すことによってデータの取得・更新などを行うことができます。

参考：[ODBC の作成の目的](https://docs.microsoft.com/ja-jp/sql/odbc/reference/why-was-odbc-created?view=sql-server-ver15)


#### ODBC接続における登場人物

ODBC アーキテクチャには、次の4つのコンポーネントがあります。	

| コンポーネント | 概要 |
|:---|:---|
|アプリケーション  |  処理を実行し、ODBC 関数を呼び出して SQL ステートメントを送信し、結果を取得します|
|ドライバーマネージャー  | アプリケーションとドライバー間の通信を管理するライブラリ。<br>アプリケーションに代わってドライバーを読み込んでアンロードします。<br>ODBC 関数呼び出しを処理するか、ドライバーに渡します|
|ドライバー  | ODBC API の関数を実装するライブラリ。<br>ODBC 関数呼び出しを処理し、SQL 要求を特定のデータソースに送信して、結果を取得しアプリケーションに返します|
| データソース | ユーザーがアクセスする必要があるデータと、DBMS にアクセスするために使用されるオペレーティングシステム、DBMS、およびネットワークプラットフォーム (存在する場合) で構成されます|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/6282e650-15f9-50b0-0bfe-f84b05088156.png)



 * アプリからは、ドライバーマネージャーをロードする。
 * ドライバーマネージャーは、アプリから与えられた接続情報に基づいて、使用するドライバーを決定して、ドライバーを読み込む。
 * ドライバーは、データソース(≒DBサーバー)に対してSQLを実行する。

という関係性となっていて、ODBC API は、

 * アプリケーションとドライバーマネージャーの間
 * ドライバーマネージャーと各ドライバーの間 (この間のインターフェースは、サービスプロバイダーインターフェイス (SPI) と呼ばれることもある)

の2か所でその役割を果たします。

ODBC の場合、アプリケーションプログラミングインターフェイス (API) と service provider interface (SPI) は同じで、ドライバーマネージャーと各ドライバーは、同じ機能に対して同じインターフェイスを持ちます。

参考：[ODBC アーキテクチャ](https://docs.microsoft.com/ja-jp/sql/odbc/reference/odbc-architecture?view=sql-server-ver15)



#### アプリケーションによるODBCアプリケーション実行の流れ

 - CONNECT(接続)
 - INITIALIZE(初期化)
 - EXECUTE(クエリ実行)
 - FETCH RESULTS or ROW COUNTS(データ/処理結果行数の取得)
 - TRANSACT(トランザクションの終了)
 - DISCONNECT(接続切断)


というのが基本的なアプリケーションの処理の流れ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/83e3cebc-96e9-b892-85b9-7655f9392476.png)



参考：[基本的な ODBC アプリケーションのステップ](https://docs.microsoft.com/ja-jp/sql/odbc/reference/develop-app/basic-odbc-application-steps?view=sql-server-ver15)




## ODBCアプリケーションからのデータベースアクセス・実践

「ODBCでデータベースにアクセスする」方法は一通りではなく、いくつものアプローチがあります。
コーディングという視点で分類してみるなら、例えば以下のようなパターンがあります。
（いろいろなRDBへのアクセスに利用できるODBCですが、実行例としてはDb2データベースで試した例を挙げます）

 * __アプリケーションコードから直接ODBC APIを呼び出すパターン：__
	  * 言語：C、COBOLなど
	  * 上の図に登場するODBC APIをアプリケーションコード中から直接呼び出す
	  * 実行例（ソースコード / コンパイル / 実行)<br> ---> [C言語+ODBC で Db2 に接続してみた](https://qiita.com/mi-kana/items/891eb9cc8a92ce8c6960)
 
 * __間接的にODBC APIを利用するパターン：__
     * 言語：Node.js、Python など
     * Node.jsの場合、アプリケーションコードからは、open , query などの node-ibm_db ドライバーのメソッドを呼び出す
    	  * 裏では、ODBC API(SQLAllocHandle, SQLExecDirect, SQLDisconnect... など) が呼び出されている
	  * 実行例（ソースコード / 実行)<br> ---> [Node.js + node-ibm_db で Db2 に接続してSELECT文を実行する](https://qiita.com/mi-kana/items/35433d6f3a08ec5d6bfe)

 * __ExcelからODBC接続して、RDBデータをExcelのワークシートに取り込む：__
	  * この利用方法であれば、コーディングは不要
	  * あらかじめODBCドライバー導入 / 接続設定だけ済ませておけばOK
	  * 利用例 (イメージ)：	  
	  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/747d545b-c6d4-18d2-1664-030db452bbdb.png)



<br>

いにしえから存在する歴史ある言語から、新しい世代の言語まで幅広く対応するODBC。
「OS、DBMS、開発言語から独立」というコンセプトは偉大ということですね。
Java/Web開発全盛期はJDBCに強くスポットライトが当たり、今でも新機能の追加はJDBCのほうが活発なようにも思いますが、長い先の未来もコンスタントに幅広く使われ続けるのは、実はODBCの方なのでしょうか。


<br>