Oracle データベース : OCI (Oracle Call Interface) の使用サンプル

データベース バージョン 21c Express Edition
プログラミング言語 C / C++
SELECT 文 : 1度に複数行を取得
公式サイトを参考に作成)
Data Interface for LOBs
https://docs.oracle.com/en/database/oracle/oracle-database/21/adlob/data-interface-for-persistent-LOBs.html#GUID-4BFDD493-F3FE-451C-9B03-21669D635586
ソース
#include <Windows.h> #include <stdio.h> #include <oci.h> #pragma comment( lib, "oci.lib" ) int main() { // 環境作成 OCIEnv* envhp; if( OCIEnvCreate(&envhp, OCI_THREADED, nullptr, nullptr, nullptr, nullptr, 0, nullptr) ) { printf_s( "Failed: OCIEnvCreate()\n" ); return 1; } // エラーハンドル作成 OCIError* errhp; OCIHandleAlloc( envhp, (dvoid **)&errhp, OCI_HTYPE_ERROR, 0, nullptr ); // サーバハンドル作成 OCIServer* srvhp; OCIHandleAlloc( envhp, (dvoid **)&srvhp, OCI_HTYPE_SERVER, 0, nullptr ); // ログイン情報 text user[] = { "user" }; text pass[] = { "password" }; text env[] = { "db-name" }; // ログイン OCISvcCtx* svchp; OCILogon2( envhp, errhp, &svchp, user, sizeof(user)-1, pass, sizeof(pass)-1, env, sizeof(env)-1, OCI_DEFAULT ); // ステートメント作成 OCIStmt* stmthp; OCIHandleAlloc( envhp, (LPVOID*)&stmthp, OCI_HTYPE_STMT, 0, nullptr ); // ステートメントへ SQL を設定 // ID … NUMBER 型。 // NAME … VARCHAR2(128) 型。 OraText STRSQL_SELECT[] = { "select ID, NAME from BASE" }; OCIStmtPrepare( stmthp, errhp, STRSQL_SELECT, sizeof(STRSQL_SELECT), OCI_NTV_SYNTAX, OCI_DEFAULT ); #if 0 // こちらを有効にすると1行ずつ取得 BYTE buffer[1024]; sb2 DstInd = 0; ub2 DstLength = 0; ub2 DstRvCode = 0; // 1列目取得定義 OCIDefine* defnp1; OCIDefineByPos( stmthp, &defnp1, errhp, 1, (LPVOID)buffer, sizeof(buffer), SQLT_STR, &DstInd, &DstLength, &DstRvCode, OCI_DEFAULT ); // 2列目取得定義なし。(必要な列のみ定義できることを示す) // SQL 実行 sword r = OCIStmtExecute( svchp, stmthp, errhp, 1, 0, nullptr, nullptr, OCI_DEFAULT ); if( OCI_SUCCESS == r ) { do { // 取得した列の値を表示 printf_s( "%s\n", buffer ); r = OCIStmtFetch2( stmthp, errhp, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT ); }while( OCI_SUCCESS == r ); } #else // こちらを有効にすると複数行を取得 // 1度に取得する行数 const int READ_COUNT = 2; // 1列目取得用バッファ OraText DstBuffer1[READ_COUNT][64] = {}; sb2 DstInd1[READ_COUNT] = {}; ub2 DstLength1[READ_COUNT] = {}; ub2 DstRvCode1[READ_COUNT] = {}; OCIIOV dvec1[READ_COUNT] = { { &DstBuffer1[0], 64 }, { &DstBuffer1[1], 64 }, }; // 2列目取得用バッファ OraText DstBuffer2[READ_COUNT][128] = {}; sb2 DstInd2[READ_COUNT] = {}; ub2 DstLength2[READ_COUNT] = {}; ub2 DstRvCode2[READ_COUNT] = {}; OCIIOV dvec2[READ_COUNT] = { { &DstBuffer2[0], 128 }, { &DstBuffer2[1], 128 }, }; // 1列目取得定義 OCIDefine* defnp1; OCIDefineByPos( stmthp, &defnp1, errhp, 1, (LPVOID)dvec1, 64, SQLT_STR, DstInd1, DstLength1, DstRvCode1, OCI_IOV ); // 2列目取得定義 OCIDefine* defnp2; OCIDefineByPos( stmthp, &defnp2, errhp, 2, (LPVOID)dvec2, 128, SQLT_STR, DstInd2, DstLength2, DstRvCode2, OCI_IOV ); // クエリ実行 & 1行目取得 sword r = OCIStmtExecute( svchp, stmthp, errhp, READ_COUNT, 0, nullptr, nullptr, OCI_DEFAULT ); if( OCI_SUCCESS == r ) { do { // 取得した列の値を表示 // ※取得行数の総数が奇数の場合、最終行の次にゴミ(前回読み込んだ行)が出力されます。 for( int i = 0; i < READ_COUNT; i ++ ) { printf_s( "%s, %s\n", (char *)dvec1[i].bfp, (char *)dvec2[i].bfp ); } // 2行目以上を取得 r = OCIStmtFetch2( stmthp, errhp, READ_COUNT, OCI_FETCH_NEXT, 0, OCI_DEFAULT ); } while( OCI_SUCCESS == r ); } #endif #f 1 OraText STRSQL_1[] = { "update PRODUCT set IMG=:1 where ID=:2" }; OCIStmt* stmthp1; OCIHandleAlloc( envhp, (LPVOID*)&stmthp1, OCI_HTYPE_STMT, 0, nullptr ); OCIStmtPrepare( stmthp1, errhp, STRSQL_1, sizeof(STRSQL_1), OCI_NTV_SYNTAX, OCI_DEFAULT ); // IMG列(Blob型)の書き込み BYTE buffer[4000] = {}; OCIBindByPos( stmthp, &bndhp2, errhp, 1, (LPVOID)buffer, sizeof(buffer), SQLT_BIN, nullptr, nullptr, nullptr, 0, nullptr, OCI_DEFAULT ); // 条件 ID列(NUMBER型)の指定 // NUMBER型は SQLT_STR を指定し文字列としても取得できる int nId = 2; OCIBindByPos( stmthp, &bndhp2, errhp, 2, (LPVOID)&nId, sizeof(nId), SQLT_INT, nullptr, nullptr, nullptr, 0, nullptr, OCI_DEFAULT ); // UPDATE 実行 OCIStmtExecute( svchp, stmthp, errhp, 1, 0, nullptr, nullptr, OCI_DEFAULT ); #endif OCIHandleFree( stmthp, OCI_HTYPE_STMT ); OCILogoff( svchp, errhp ); OCIHandleFree( srvhp, OCI_HTYPE_SERVER ); OCIHandleFree( errhp, OCI_HTYPE_ERROR ); OCIHandleFree( envhp, OCI_HTYPE_ENV ); return 0; }