本記事では、OceanBase Connector/ODBCとOceanBaseデータベースを使用してアプリケーションを構築し、テーブルの作成、データの挿入、データのクエリなどの基本操作を実装する方法について説明します。
前提条件
OceanBaseデータベースがインストール済みで、Oracleモードのユーザーテナントが作成済みであること。OceanBaseデータベースのインストールの詳細については、デプロイの概要を参照してください。
Visual Studioがインストール済みであること。
OceanBase Connector/ODBCドライバーがインストール済みであること。
説明
OceanBase公式ダウンロードセンターのOceanBase Dedicatedページのドライバーとミドルウェアモジュールから、OceanBase ODBCドライバープログラムのWindows版インストールパッケージをダウンロードしてください。Windows版OceanBase Connector/ODBCドライバーインストールパッケージはワンクリックデプロイ式で、デフォルトのガイド手順に従ってインストール可能です。
操作手順
説明
本記事で示されている操作手順は、Windows環境下でVisual Studio Community 2019を使用して、このプロジェクトをコンパイルおよび実行する方法です。他のOS環境やコンパイラを使用している場合は、操作手順が若干異なる場合があります。
c-oceanbase-odbcプロジェクトを開きます。c-oceanbase-odbcプロジェクトのプロパティを設定します。- OceanBaseデータベースの接続情報を取得します。
c-oceanbase-odbcプロジェクト内のデータベース接続情報を修正します。- プロジェクトをビルドします。
- アプリケーションを実行します。
- 出力結果を確認します。
ステップ1:c-oceanbase-odbcプロジェクトを開く
Visual Studio Community 2019を起動します。
既存のプロジェクトを開きます。
Visual Studio Community 2019の開始画面で、「使用を開始する」の下にある プロジェクトまたはソリューションを開く(P) ボタンをクリックします。または、Visual Studio Community 2019の開始画面で、「使用を開始する」の下にある コードなしで続行(W) ボタンをクリックするか、上部のメニューバーから ファイル -> 開く -> プロジェクト / ソリューション(P) を選択します。
c-oceanbase-odbcプロジェクト フォルダに移動し、プロジェクトファイル(
c-oceanbase-odbc.slnまたはc-oceanbase-odbc.vcxproj)を選択して 開く をクリックします。
ステップ2:c-oceanbase-odbcプロジェクトのプロパティを設定する
プロジェクトのプロパティページを開きます。
ソリューションエクスプローラー で選択したプロジェクトを右クリックし、コンテキストメニューで プロパティ を選択するか、Visual Studioの上部メニューバーで プロジェクト -> プロパティ を選択するか、ショートカットキー Alt + Enter を使用します。
構成マネージャーの設定を行います。
プロパティページで、上部にある 設定(C) ドロップダウンメニューを選択します。ドロップダウンメニューで、Debug を選択します。
プロパティページで、上部にある プラットフォーム(P) のドロップダウンメニューを選択します。ドロップダウンメニューで、x64 を選択します。
文字セットの設定を行います。
プロパティページで 詳細設定 タブを選択し、文字セット 項目を見つけます。ドロップダウンメニューで、マルチバイト文字セットを使用する を選択します。
ステップ3:OceanBaseデータベース接続情報を取得する
OceanBaseデータベースのデプロイ担当者または管理者から、該当するデータベース接続文字列を取得します。
例:
obclient -hxxx.xxx.xxx.xxx -P2881 -usys@oracle001 -p******
パラメータの説明:
-h:OceanBaseデータベースの接続IPアドレスを提供します。ODP接続方式ではODPアドレスを使用し、直接接続方式ではOBServerノードのIPアドレスを使用します。-P:OceanBaseデータベースの接続ポートを提供します。ODP接続方式のデフォルトは2883で、ODPデプロイ時にカスタマイズ可能です。直接接続方式のデフォルトは2881で、OceanBaseデータベースのデプロイ時にカスタマイズ可能です。-u:テナントの接続アカウント。ODP接続の一般的な形式:ユーザー名@テナント名#クラスタ名またはクラスタ名:テナント名:ユーザー名。直接接続方式の形式:ユーザー名@テナント名。-p:アカウントのパスワード。
接続文字列の詳細については、OBClientによるOceanBaseテナントへの接続を参照してください。
ステップ4:c-oceanbase-odbcプロジェクトのデータベース接続情報を修正する
ステップ3:OceanBaseデータベース接続情報を取得する に記載されている情報に基づいて、test_tbl1.cpp ファイル内のデータベース接続情報を修正します。
例:
char* mydriver = (char*)"Driver={OceanBase ODBC 2.0 Driver};Server=xxx.xxx.xxx.xxx;Port=2881;Database=sys;User=sys@oracle001;Password=******;Option=3;";
ステップ5:プロジェクトをビルドします
ビルドメニューを選択し、ソリューションのビルド を選択します。ビルドプロセス中にコンパイラの出力とエラーや警告情報が表示されます。
ステップ6:アプリケーションを実行する
デバッグメニューを選択し、デバッグの開始 または デバッグなしで開始 を選択してアプリケーションを実行します。
ステップ7:出力結果を確認する
出力結果はデバッグコンソールに表示されます。プログラムの設計ロジックとコードに基づいて、出力の処理方法を判断できます。
プロジェクトコードについて
c-oceanbase-odbc をクリックして、プロジェクトコードをダウンロードします。これは、c-oceanbase-odbc.zip という名前の圧縮ファイルです。
解凍すると、c-oceanbase-odbc という名前のフォルダが作成されます。ディレクトリ構造は以下のとおりです:
c-oceanbase-odbc
├─ c-oceanbase-odbc.sln
├─ c-oceanbase-odbc.vcxproj
├─ c-oceanbase-odbc.vcxproj.filters
├─ c-oceanbase-odbc.vcxproj.user
└─ test_tbl1.cpp
ファイルの説明:
c-oceanbase-odbc.sln:Visual Studioのソリューションファイルです。1つまたは複数のプロジェクトを管理するために使用されます。c-oceanbase-odbc.vcxproj:Visual Studioのプロジェクトファイルです。C/C++プロジェクトの構造と設定を記述するために使用されます。c-oceanbase-odbc.vcxproj.filters:Visual Studioのプロジェクトフィルターファイルです。プロジェクト内のファイルのディレクトリ構造と編成方法を定義するために使用されます。c-oceanbase-odbc.vcxproj.user:ユーザー固有のプロジェクト設定を格納するファイルです。test_tbl1.cpp:データテーブルの構造を定義し、データテーブル操作を実装したソースコードファイルです。
test_tbl1.cppファイルのコード解説
test_tbl1.cpp ファイルは、test_tbl1 という名前のデータテーブルを定義するために使用され、データテーブルの作成、データの挿入、クエリの操作を実装しています。
本記事の test_tbl1.cpp ファイルのコードには、主に以下の部分が含まれています:
ヘッダーファイルをインポートします。
ヘッダーファイル
stdio.h、assert.h、windows.h、sql.h、sqlext.hをインクルードします。コード:
#include <stdio.h> #include <assert.h> #include <windows.h> #include <sql.h> #include <sqlext.h>odbc_print_error関数を定義します。プログラム実行中にODBC関連のエラーが発生した場合、この関数が呼び出されてエラー情報を出力します。具体的な手順は以下のとおりです:
- 関数名を
odbc_print_errorとして定義し、パラメータSQLSMALLINT HandleTypeとSQLHANDLE Handleを指定します。これらはエラー情報に対応するハンドルのタイプとハンドルを指定するために使用されます。 - ODBCからエラー情報を取得するために使用する変数を定義します。これらの変数のタイプと名前は、ODBC APIで定義されたデータ型と名前です。
SQLGetDiagRec()を使用して、ODBCで最後に発生したエラー情報を取得します。この関数を呼び出すと、SQLState、NativeError、SQLMessageの各配列にエラー情報の関連内容が格納されます。fprintf関数を使用して、エラー情報を標準出力ストリームに出力します。[%s] (%d) %s\nは出力フォーマットで、printf関数に似たフォーマット文字列を使用します。%sは文字列タイプのデータの出力に、%dは整数タイプのデータの出力に使用され、\nは改行を表します。SQLState、NativeError、SQLMessageは、それぞれフォーマット文字列内の3つのパラメータに対応し、出力するエラー情報の内容を表します。
コード:
static void odbc_print_error(SQLSMALLINT HandleType, SQLHANDLE Handle) { SQLCHAR SQLState[6]; SQLINTEGER NativeError; SQLCHAR SQLMessage[SQL_MAX_MESSAGE_LENGTH] = { 0 }; SQLSMALLINT TextLengthPtr; SQLGetDiagRec(HandleType, Handle, 1, SQLState, &NativeError, SQLMessage, SQL_MAX_MESSAGE_LENGTH, &TextLengthPtr); fprintf(stdout, "[%s] (%d) %s\n", SQLState, NativeError, SQLMessage); }- 関数名を
ASSERT_CHECK関数を定義します。この関数の役割は、ODBC関数呼び出しの戻り値をチェックして処理することです。つまり、ODBC API関数の戻り値にエラーが発生していないかどうかをチェックし、エラーが発生している場合はエラー情報を出力してプログラムを終了します。具体的な手順は以下のとおりです:
- マクロ名を
ASSERT_CHECKとして定義し、パラメータSQLSMALLINT HandleType、SQLHANDLE Handle、SQLRETURN rcodeを指定します。これらはそれぞれODBCハンドルタイプ、ODBCハンドル、ODBC API関数呼び出しの戻り値です。 ifステートメントを使用してODBC API関数の戻り値を判定します。戻り値がSQL_SUCCESSまたはSQL_SUCCESS_WITH_INFOと等しくない場合は、関数呼び出しでエラーが発生したことを表します。odbc_print_error関数を呼び出してODBCエラー情報を出力します。assert関数を呼び出して、プログラム実行中にアサーションチェックを行います。つまり、ODBC関数呼び出しでエラーが発生した場合、プログラムは中断されます。
コード:
static void ASSERT_CHECK(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLRETURN rcode) { if (rcode != SQL_SUCCESS && rcode != SQL_SUCCESS_WITH_INFO) { odbc_print_error(HandleType, Handle); assert(0); } }- マクロ名を
main関数を定義します。プログラムのエントリポイントとなる関数
mainを定義し、整数値を返します。main関数内には、データベース接続とデータ操作の関連コードを記述します。コード:
int main() { // 環境ハンドルの申請 // ODBCバージョンの環境プロパティの設定 // 接続ハンドルの割り当て // データソースへの接続 // テーブルの作成 // データの挿入 // データのクエリ // クリーンアップ作業、具体的なリソースハンドルの解放 }変数を定義します。
変数
henvを定義します。これはODBC環境ハンドルタイプのオブジェクトで、ODBC接続とリソースの割り当てを管理するために使用されます。OutConnStrとOutConnStrLenは、接続文字列と文字列の長さを格納するために使用されます。これらのパラメータをデータベースに接続する際にSQLDriverConnect関数に渡すことにより、データベースへの接続が成功した際の戻り値やその他の接続情報を取得します。コード:
HENV henv; SQLCHAR OutConnStr[255]; SQLSMALLINT OutConnStrLen;環境ハンドルを申請します。
SQLAllocHandle関数を使用してODBC環境ハンドルを割り当てます。ASSERT_CHECK関数でハンドルの割り当て結果をチェックし、割り当てが成功したことを確認します。具体的な手順は以下のとおりです:SQLAllocHandle関数を実行すると、関数の実行結果を示すSQLRETURNタイプの値が返されます。コード内では、この戻り値はrcode変数に格納されます。SQLAllocHandle関数のパラメータは以下のとおりです:SQL_HANDLE_ENV:割り当てるハンドルのタイプを指定します。ここではSQL_HANDLE_ENVで、環境ハンドルを割り当てることを表します。SQL_NULL_HANDLE:親ハンドルを指定します。ここではSQL_NULL_HANDLEで、親ハンドルがないことを表します。&henv:割り当てられたハンドルを格納する変数へのポインタです。ここではhenvで、環境ハンドルの変数です。
ASSERT_CHECK関数は、SQLAllocHandle関数の戻り値rcodeをチェックするために使用されます。rcodeがSQL_SUCCESSまたはSQL_SUCCESS_WITH_INFOでない場合、つまりハンドルの割り当てに失敗した場合、ASSERT_CHECK関数はodbc_print_error関数を呼び出してエラー情報を出力し、assertマクロを使用してプログラムの実行を終了します。
コード:
SQLRETURN rcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); ASSERT_CHECK(SQL_HANDLE_ENV, henv, rcode);ODBCバージョンの環境プロパティを設定します。
SQLSetEnvAttr関数を使用して、ODBC環境のプロパティを設定します。この関数は、環境レベルのプロパティを設定することにより、データベース接続とドライバーの動作に影響を与えることができます。ASSERT_CHECK関数を使用してプロパティ設定の結果をチェックし、設定が成功したことを確認します。具体的な手順は以下のとおりです:SQLSetEnvAttr関数を実行すると、関数の実行結果を示すSQLRETURNタイプの値が返されます。コード内では、この戻り値はrcode変数に格納されます。SQLSetEnvAttr関数のパラメータは以下のとおりです:henv:ODBC環境ハンドルで、プロパティを設定する環境オブジェクトを指定します。SQL_ATTR_ODBC_VERSION:設定する環境プロパティタイプを指定します。ここではSQL_ATTR_ODBC_VERSIONで、ODBCバージョンのプロパティを設定することを表します。(void*)SQL_OV_ODBC3:プロパティ値へのポインターです。ここではSQL_OV_ODBC3で、ODBCバージョンをODBC 3.xバージョンに設定することを表します。0:プロパティ値の長さです。ここでは、プロパティ値が列挙定数であるため、長さは0です。
ASSERT_CHECK関数は、SQLSetEnvAttr関数の戻り値rcodeをチェックするために使用されます。rcodeがSQL_SUCCESSまたはSQL_SUCCESS_WITH_INFOでない場合、つまりプロパティ設定が失敗した場合、ASSERT_CHECK関数はodbc_print_error関数を呼び出してエラー情報を出力し、assertマクロを使用してプログラムの実行を終了します。
コード:
rcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); ASSERT_CHECK(SQL_HANDLE_ENV, henv, rcode);接続ハンドルを割り当てます。
SQLAllocHandle関数を使用して、ODBC接続ハンドルを割り当てます。ASSERT_CHECK関数を使用してハンドルの割り当ての結果をチェックし、割り当てが成功したことを確認します。具体的な手順は以下のとおりです:SQLAllocHandle関数を実行すると、関数の実行結果を示すSQLRETURNタイプの値が返されます。コード内では、この戻り値はrcode変数に格納されます。SQLAllocHandle関数のパラメータは以下のとおりです:SQL_HANDLE_DBC:割り当てるハンドルのタイプを指定します。ここではSQL_HANDLE_DBCで、接続ハンドルを割り当てることを表します。henv:割り当て済みのODBC環境ハンドルで、親ハンドルとして接続ハンドルと関連付けられます。&hdbc:割り当てられた接続ハンドルを格納する変数へのポインタです。
ASSERT_CHECK関数は、SQLAllocHandle関数の戻り値rcodeをチェックするために使用されます。rcodeがSQL_SUCCESSまたはSQL_SUCCESS_WITH_INFOでない場合、つまりハンドルの割り当てに失敗した場合、ASSERT_CHECK関数はodbc_print_error関数を呼び出してエラー情報を出力し、assertマクロを使用してプログラムの実行を終了します。
コード:
SQLHDBC hdbc; rcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); ASSERT_CHECK(SQL_HANDLE_DBC, hdbc, rcode);データソースに接続します。
SQLDriverConnect関数を使用して、指定されたODBCデータソースに接続します。ASSERT_CHECK関数を使用して接続操作の結果をチェックし、接続が成功したことを確認します。具体的な手順は以下のとおりです:接続文字列
mydriverを定義します。この文字列は、データベースへの接続に必要な詳細情報を記述するために使用されます。この文字列には以下の部分が含まれます:Driver={OceanBase ODBC 2.0 Driver}:使用するODBCドライバープログラムをOceanBase ODBC 2.0 Driverと指定します。Server=your_ip:データベースサーバーのIPアドレスを指定します。Port=your_port:データベースへの接続に使用するポート番号を指定します。Database=your_schema:接続するデータベース名を指定します。User=your_use:データベースへの接続に使用するユーザー名を指定します。Password=your_password:データベースへの接続に使用するパスワードを指定します。Option=3:接続オプションを指定します。値の3は、TCP/IP接続を使用することを表します。
SQLDriverConnect関数を使用して、指定されたODBCデータソースに接続します。関数を実行すると、関数の実行結果を示すSQLRETURNタイプの値が返されます。コード内では、この戻り値はrcode変数に格納されます。この関数のパラメータは以下のとおりです:hdbc:ODBC接続ハンドルで、データソースとの接続を確立するために使用されます。NULL:予約パラメータです。使用されません。mydriver:ドライバープログラム名、データベースアドレス、ポート番号、データベース名、ユーザー名、パスワードなど、データベースへの接続に必要なすべての情報が含まれる接続文字列です。strlen((char*)mydriver) + 1:接続文字列の長さです。OutConnStr:接続文字列を格納するためのSQLCHARタイプのバッファーです。255:バッファの長さです。&OutConnStrLen:接続文字列の実際の長さを格納する変数へのポインタです。SQL_DRIVER_NOPROMPT:接続時にプロンプトボックスを表示しないことを指示する接続フラグです。
ASSERT_CHECK関数は、SQLDriverConnect関数の戻り値rcodeをチェックするために使用されます。rcodeがSQL_SUCCESSまたはSQL_SUCCESS_WITH_INFOでない場合、つまり接続が失敗した場合、ASSERT_CHECK関数はodbc_print_error関数を呼び出してエラー情報を出力し、assertマクロを使用してプログラムの実行を終了します。
コード:
char* mydriver = (char*)"Driver={OceanBase ODBC 2.0 Driver};Server=your_ip;Port=your_port;Database=your_schema;User=your_use;Password=your_password;Option=3;"; rcode = SQLDriverConnect(hdbc, NULL, (SQLCHAR*)mydriver, strlen((char*)mydriver) + 1, OutConnStr, 255, &OutConnStrLen, SQL_DRIVER_NOPROMPT); ASSERT_CHECK(SQL_HANDLE_DBC, hdbc, rcode);OceanBaseデータベースへの接続に必要なパラメータの説明:
your_ip:OceanBaseデータベースの接続IPアドレスを提供します。ODP接続方式ではODPアドレスを使用し、直接接続方式ではOBServerノードのIPアドレスを使用します。your_port:OceanBaseデータベースの接続ポートを提供します。ODP接続方式のデフォルトは2883で、ODPデプロイ時にカスタマイズ可能です。直接接続方式のデフォルトは2881で、OceanBaseデータベースのデプロイ時にカスタマイズ可能です。your_schema:アクセスするスキーマ名。your_user:テナントの接続アカウント。ODP接続方式の形式:ユーザー名@テナント名#クラスタ名またはクラスタ名:テナント名:ユーザー名。直接接続方式の形式:ユーザー名@テナント名。your_password:アカウントのパスワード。
テーブルを作成します。
SQLAllocHandle関数を使用して、ODBCステートメントハンドルを割り当てます。次にSQLExecDirect関数を使用して、テーブルを作成するSQLステートメントを実行します。ASSERT_CHECK関数を使用してハンドル割り当てとステートメント実行の結果をチェックし、操作が成功したことを確認します。最後に、SQLFreeHandle関数を使用してステートメントハンドルを解放し、リソースを解放します。具体的な手順は以下のとおりです:ODBCステートメントハンドル
stmtを宣言します。SQLAllocHandle関数を使用して、ODBCステートメントハンドルを割り当てます。ASSERT_CHECK関数を使用して、SQLAllocHandle関数の戻り値rcodeをチェックし、ハンドルの割り当てに成功したことを確認します。SQLExecDirect関数を使用してSQLステートメントを実行します。ここでは、CREATE TABLEステートメントを実行して、test_tbl1という名前のテーブルを作成します。ASSERT_CHECK関数を使用して、SQLExecDirect関数の戻り値rcodeをチェックし、ステートメントの実行に成功したことを確認します。SQLFreeHandle関数を使用して、ODBCステートメントハンドルを解放します。
コード:
SQLHSTMT stmt; rcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &stmt); ASSERT_CHECK(SQL_HANDLE_STMT, stmt, rcode); rcode = SQLExecDirect(stmt, (SQLCHAR*)"CREATE TABLE test_tbl1(id NUMBER PRIMARY KEY, name VARCHAR2(50),age NUMBER NOT NULL)", SQL_NTS); ASSERT_CHECK(SQL_HANDLE_STMT, stmt, rcode); SQLFreeHandle(SQL_HANDLE_STMT, stmt);データを挿入します。
SQLAllocHandle関数を使用して、ODBCステートメントハンドルを割り当てます。次にSQLExecDirect関数を使用して、データベーステーブルにデータを挿入するSQLステートメントを実行します。ASSERT_CHECK関数を使用してハンドル割り当てとステートメント実行の結果をチェックし、操作が成功したことを確認します。最後に、SQLFreeHandle関数を使用してステートメントハンドルを解放し、リソースを解放します。具体的な手順は以下のとおりです:SQLAllocHandle関数を使用して、ODBCステートメントハンドルを割り当てます。ASSERT_CHECK関数を使用して、SQLAllocHandle関数の戻り値rcodeをチェックし、ハンドルの割り当てに成功したことを確認します。SQLExecDirect関数を使用してSQLステートメントを実行します。ここでは、INSERT INTOステートメントを実行して、test_tbl1テーブルに3件のレコードを挿入します。ASSERT_CHECK関数を使用して、SQLExecDirect関数の戻り値rcodeをチェックし、ステートメントの実行に成功したことを確認します。SQLFreeHandle関数を使用して、ODBCステートメントハンドルを解放します。
コード:
rcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &stmt); ASSERT_CHECK(SQL_HANDLE_STMT, stmt, rcode); rcode = SQLExecDirect(stmt, (SQLCHAR*)"INSERT INTO test_tbl1 (id,name,age) VALUES (1,'Tom', 18),(2,'Jerry', 20),(3,'Bob', 22)", SQL_NTS); ASSERT_CHECK(SQL_HANDLE_STMT, stmt, rcode); SQLFreeHandle(SQL_HANDLE_STMT, stmt);データのクエリを実行します。
SQLAllocHandle関数を使用して、ODBCステートメントハンドルを割り当てます。次にSQLExecDirect関数を使用して、結果セットを取得するSQLステートメントを実行します。続いて、SQLBindCol関数を使用して結果セットの列を変数にバインドし、SQLFetch関数を使用して結果セットを行ごとに取得します。whileループで、rcodeの値に基づいて結果セット内のデータを出力します。最後に、SQLFreeHandle関数を使用してステートメントハンドルを解放し、リソースを解放します。具体的な手順は以下のとおりです:SQLAllocHandle関数を使用して、ODBCステートメントハンドルを割り当てます。ASSERT_CHECK関数を使用して、SQLAllocHandle関数の戻り値rcodeをチェックし、ハンドルの割り当てに成功したことを確認します。SQLExecDirect関数を使用してSQLステートメントを実行します。ここでは、SELECTステートメントを実行して、test_tbl1テーブルからすべての行を取得します。ASSERT_CHECK関数を使用して、SQLExecDirect関数の戻り値rcodeをチェックし、ステートメントの実行に成功したことを確認します。SQLLENタイプの変数resを宣言し、バインドされた列の操作の結果を格納します。結果セットの対応する列の値を格納するために、
SQLINTEGERタイプの2つの変数idとageを宣言します。結果セットの対応する列の値を格納するために、
SQLCHARタイプの配列nameを宣言します。SQLBindCol関数を使用して、結果セットの1番目の列を変数idにバインドします。SQLBindCol関数を使用して、結果セットの2番目の列を配列nameにバインドします。SQLBindCol関数を使用して、結果セットの3番目の列を変数ageにバインドします。SQLFetch関数を使用して結果セットの行を取得し、行内のデータをバインドされた変数に格納します。whileループは、すべての行が取得されるまで継続して実行されます。whileループで、rcodeの値を判定して、対応する行のデータを出力します。rcodeがSQL_ERRORの場合、エラー情報を出力します。SQLFreeHandle関数を使用して、ODBCステートメントハンドルを解放します。
コード:
rcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &stmt); ASSERT_CHECK(SQL_HANDLE_STMT, stmt, rcode); rcode = SQLExecDirect(stmt, (SQLCHAR*)"SELECT * FROM test_tbl1", SQL_NTS); ASSERT_CHECK(SQL_HANDLE_STMT, stmt, rcode); SQLLEN res = SQL_NTS; SQLINTEGER id, age; SQLCHAR name[255]; SQLBindCol(stmt, 1, SQL_C_SLONG, &id, sizeof(id), &res); SQLBindCol(stmt, 2, SQL_C_CHAR, name, sizeof(name), &res); SQLBindCol(stmt, 3, SQL_C_SLONG, &age, sizeof(age), &res); while ((rcode = SQLFetch(stmt)) != SQL_NO_DATA_FOUND) { if (rcode == SQL_ERROR) { printf("sql error!\n"); } else { printf("id:%d, name:%s, age:%ld\n", id, name, age); } } SQLFreeHandle(SQL_HANDLE_STMT, stmt);クリーンアップ作業を実行し、具体的なリソースハンドルを解放します。
データベースとの接続を切断し、関連するODBCハンドルと環境ハンドルを解放して、リソースを解放します。SQLDisconnect関数とSQLFreeHandle関数を呼び出して、データベースとの接続を正しく閉じ、関連ハンドルを解放します。最後に、プログラムの実行が成功したことを示す0を返します。具体的な手順は以下のとおりです:
SQLDisconnect関数を使用して、データベースとの接続を切断します。
SQLFreeHandle関数を使用して、データベース接続ハンドルを解放します。
SQLFreeHandle関数を使用して、ODBC環境ハンドルを解放します。
プログラムの実行が成功したことを示す0を返します。
コード:
SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC, hdbc); SQLFreeHandle(SQL_HANDLE_ENV, henv); return 0;
全コード表示
#include <stdio.h>
#include <assert.h>
#include <windows.h>
#include <sql.h>
#include <sqlext.h>
static void odbc_print_error(SQLSMALLINT HandleType, SQLHANDLE Handle)
{
SQLCHAR SQLState[6];
SQLINTEGER NativeError;
SQLCHAR SQLMessage[SQL_MAX_MESSAGE_LENGTH] = { 0 };
SQLSMALLINT TextLengthPtr;
SQLGetDiagRec(HandleType, Handle, 1, SQLState, &NativeError, SQLMessage, SQL_MAX_MESSAGE_LENGTH, &TextLengthPtr);
fprintf(stdout, "[%s] (%d) %s\n", SQLState, NativeError, SQLMessage);
}
static void ASSERT_CHECK(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLRETURN rcode)
{
if (rcode != SQL_SUCCESS && rcode != SQL_SUCCESS_WITH_INFO) {
odbc_print_error(HandleType, Handle);
assert(0);
}
}
int main()
{
HENV henv;
SQLCHAR OutConnStr[255];
SQLSMALLINT OutConnStrLen;
SQLRETURN rcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
ASSERT_CHECK(SQL_HANDLE_ENV, henv, rcode);
rcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
ASSERT_CHECK(SQL_HANDLE_ENV, henv, rcode);
SQLHDBC hdbc;
rcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
ASSERT_CHECK(SQL_HANDLE_DBC, hdbc, rcode);
char* mydriver = (char*)"Driver={OceanBase ODBC 2.0 Driver};Server=your_ip;Port=your_port;Database=your_schema;User=your_use;Password=your_password;Option=3;";
rcode = SQLDriverConnect(hdbc, NULL, (SQLCHAR*)mydriver, strlen((char*)mydriver) + 1, OutConnStr, 255, &OutConnStrLen, SQL_DRIVER_NOPROMPT);
ASSERT_CHECK(SQL_HANDLE_DBC, hdbc, rcode);
SQLHSTMT stmt;
rcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &stmt);
ASSERT_CHECK(SQL_HANDLE_STMT, stmt, rcode);
rcode = SQLExecDirect(stmt, (SQLCHAR*)"CREATE TABLE test_tbl1(id NUMBER PRIMARY KEY, name VARCHAR2(50),age NUMBER NOT NULL)", SQL_NTS);
ASSERT_CHECK(SQL_HANDLE_STMT, stmt, rcode);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
rcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &stmt);
ASSERT_CHECK(SQL_HANDLE_STMT, stmt, rcode);
rcode = SQLExecDirect(stmt, (SQLCHAR*)"INSERT INTO test_tbl1 (id,name,age) VALUES (1,'Tom', 18),(2,'Jerry', 20),(3,'Bob', 22)", SQL_NTS);
ASSERT_CHECK(SQL_HANDLE_STMT, stmt, rcode);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
rcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &stmt);
ASSERT_CHECK(SQL_HANDLE_STMT, stmt, rcode);
rcode = SQLExecDirect(stmt, (SQLCHAR*)"SELECT * FROM test_tbl1", SQL_NTS);
ASSERT_CHECK(SQL_HANDLE_STMT, stmt, rcode);
SQLLEN res = SQL_NTS;
SQLINTEGER id, age;
SQLCHAR name[255];
SQLBindCol(stmt, 1, SQL_C_SLONG, &id, sizeof(id), &res);
SQLBindCol(stmt, 2, SQL_C_CHAR, name, sizeof(name), &res);
SQLBindCol(stmt, 3, SQL_C_SLONG, &age, sizeof(age), &res);
while ((rcode = SQLFetch(stmt)) != SQL_NO_DATA_FOUND)
{
if (rcode == SQL_ERROR) {
printf("sql error!\n");
}
else {
printf("id:%d, name:%s, age:%ld\n", id, name, age);
}
}
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
return 0;
}
関連ドキュメント
OceanBaseデータベースへの接続に関する詳細については、接続方法の概要を参照してください。
OceanBase Connector/ODBCに関する詳細については、OceanBase Connector/ODBCを参照してください。
クリックしてc-oceanbase-odbcサンプルプロジェクトをダウンロード