小さい頃はエラ呼吸

いつのまにやら肺で呼吸をしています。


【VC++】OCIを使ってOracle DBに接続するコード書いたよ。

はじめに

VC++でOCI(Oracle Call Interface)を使ってOracleに接続して、レコードをselectするコードを書いてみました。
参考にしたのは以下のページです。

C言語の勉強3 Oracleデータベース接続 - 日記とかプログラムとかC言語の勉強3 Oracleデータベース接続 - 日記とかプログラムとか
OCI (Oracle Call Interface)OCI (Oracle Call Interface)
新・門外不出のOracle現場ワザ エキスパートが明かす運用・管理の極意 (DB Selection)
小田 圭二 大塚 信男 五十嵐 建平 谷 敦雄 宮崎 博之 神田 達成 村方 仁
翔泳社
売り上げランキング: 293,715

テーブルレイアウト

f:id:replication:20140823222024p:plain

準備

1.Oracle Clientをインストールします。

2.ociのヘッダファイルをインクルードします。
f:id:replication:20140823223116p:plain
3.ociのlibファイルパスを指定します。
f:id:replication:20140823223204p:plain
4.追加の依存ファイルを指定します。
f:id:replication:20140823223232p:plain
5.Oracle Clientのインストールディレクトリ¥network¥admin配下にtnsnames.oraを配置します。

ぼくの環境の場合、C:\app\Administrator\product\11.2.0\dbhome_1\NETWORK\ADMIN配下にサーバ側のtnsnames.oraがあったので、これをクライアント側C:\app\Administrator\product\11.2.0\client_1\network\adminにコピーしました。

サンプルコード
// OracleApp01.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"
#include <string.h>
#include <oci.h>

int _tmain(int argc, _TCHAR* argv[])
{

  // OCI環境を作成する
  OCIEnv* envhp;
  sword status = OCI_SUCCESS;
  status = OCIEnvCreate(&envhp, OCI_DEFAULT, 0, 0, 0, 0, 0, 0);
  if (status != OCI_SUCCESS)
  {
    printf("OCIEnvCreate - error : %d.\n", status);
    return -1;
  }

  // 各種ハンドルを割り当てる(エラー・ハンドル)
  OCIError* errhp;
  status = OCIHandleAlloc(envhp, (dvoid **)&errhp, OCI_HTYPE_ERROR, 0, 0);
  if (status != OCI_SUCCESS)
  {
    printf("OCIHandleAlloc - error : %d.\n", status);
    return -1;
  }

  // ログイン・セッションを作成する
  OCISvcCtx* svchp;
  char* username = "ユーザ名";
  char* password = "パスワード";
  char* dbname = "DB名";
  status = OCILogon(envhp, errhp, &svchp, (OraText*)username, strlen(username),
                    (OraText*)password, strlen(password), (OraText*)dbname, strlen(dbname));

  if (status != OCI_SUCCESS)
  {
    printf("OCILogon - error : %d.\n", status);
    return -1;
  }

  // 各種ハンドルを割り当てる(文ハンドル)
  OCIStmt* stmtp;
  status = OCIHandleAlloc(envhp, (dvoid **)&stmtp, OCI_HTYPE_STMT, 0, 0);

  if (status != OCI_SUCCESS)
  {
    printf("OCIHandleAlloc - error : %d.\n", status);
    goto finallyFree;
  }

  // 実行するSQL文またはPL/SQL文を準備する
  char* stmt = "SELECT name, furigana FROM TABLE01";
  status = OCIStmtPrepare(stmtp, errhp, (OraText*)stmt, strlen(stmt), OCI_NTV_SYNTAX, OCI_DEFAULT);

  if (status != OCI_SUCCESS)
  {
    printf("OCIStmtPrepare - error : %d.\n", status);
    goto finallyFree;
  }

  // 選択リスト内の項目を型と出力データ・バッファに関連付ける
  OCIDefine* dfnp, *dfnp2;
  char message1[64] = {0};
  char message2[64] = {0};
  status = OCIDefineByPos(stmtp, &dfnp, errhp, 1, message1, sizeof(message1), SQLT_STR, 0, 0, 0, OCI_DEFAULT);
  status = OCIDefineByPos(stmtp, &dfnp2, errhp, 2, message2, sizeof(message2), SQLT_STR, 0, 0, 0, OCI_DEFAULT);

  if (status != OCI_SUCCESS)
  {
    printf("OCIDefineByPos - error : %d.\n", status);
    goto finallyFree;
  }

  // 準備済みのSQL文を実行する
  status = OCIStmtExecute(svchp, stmtp, errhp, 1, 0, NULL, NULL, OCI_DEFAULT);
  if (status != OCI_SUCCESS)
  {
    printf("OCIStmtExecute - error : %d.\n", status);
    goto finallyFree;
  }

  while ( status == OCI_SUCCESS )
  {
    printf("%s\n", message1);
    printf("%s\n", message2);
    // 結果セットから行をフェッチする
    status = OCIStmtFetch2(stmtp, errhp, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
  }

finallyFree:
  // ハンドル解放
  OCIHandleFree(stmtp, OCI_HTYPE_STMT);
  // OCILogonを使用して作成したログイン・セッションを解放する
  OCILogoff(svchp, errhp);
  // ハンドル解放
  OCIHandleFree(errhp, OCI_HTYPE_ERROR);

  return 0;
}
実行結果

f:id:replication:20140823222313p:plain