#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;
}