ヘッダーをスキップ
Oracle Call Interfaceプログラマーズ・ガイド
11g リリース1(11.1)
E05677-02
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

2 OCIプログラミングの基本

この章では、Oracle Call Interface(OCI)を使用してプログラムを作成する際に必要となる基本概念の概要を説明します。

この章は、次の項目で構成されています。

OCIプログラミングの概要

この章では、OCIアプリケーションの開発における基本的な概念とプロシージャについて説明します。この章を読み終えると、基本的なOCIアプリケーションの作成に必要なツールについてほとんど習得したことになります。

この章は、次の項に大きくわかれています。

新規ユーザーは、この章の情報に特に注意してください。この章は、以降の章を理解する基本となります。以降の章は、この章の内容を補足しています。


関連項目

  • 多言語環境に適用されるOCI関数の詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。

  • カートリッジ・サービスに適用されるOCI関数の詳細は、『Oracle Databaseデータ・カートリッジ開発者ガイド』を参照してください。


ヘッダー・ファイル

現行リリースでは、LinuxおよびUNIXプラットフォームでOCIおよびOCCIクライアント・アプリケーションを開発するために必要なOCI/OCCIヘッダー・ファイルは$ORACLE_HOME/rdbms/publicディレクトリにあります。

すべてのデモ・プログラムとヘッダー・ファイルは、引き続き$ORACLE_HOME/rdbms/demoディレクトリにあります。すべてのデモ・プログラムに関して、これらのファイルはExamplesメディアからのみインストールできます。これらのプログラムの名前とその目的の詳細は、付録B「OCIデモ・プログラム」を参照してください。

開発に必要なOCI/OCCIヘッダー・ファイルは、$ORACLE_HOME/rdbms/publicにあり、Oracle Databaseサーバー環境でもOracle Databaseクライアント管理およびカスタム環境でも使用できます。

Makefile

demoディレクトリに複数のMakefileが用意されています。各Makefileのコメントには、OCI実行可能ファイルを作成する際の指示が含まれています。コンパイル・エラーとリンク・エラーを回避するために、できるかぎりこれらのデモ用Makefileを使用することをお薦めします。

demo_rdbms.mkファイルは$ORACLE_HOME/rdbms/demoディレクトリ内にあるサンプルMakefileです。コメントには、デモ用OCIプログラムのビルド方法が含まれています。demo_rdbms.mkファイルには、すでに$ORACLE_HOME/rdbms/publicディレクトリが含まれています。独自にカスタマイズしたMakefileが、INCLUDEパスの$ORACLE_HOME/rdbms/publicディレクトリにあることを確認してください。

同じディレクトリに、32ビット・クライアント実行可能ファイル作成用のMakefileであるdemo_rdbms32.mkがあります。このMakefileでは、demo_rdbms.mkを使用して、外部プロシージャ・コール用にデータベース・サーバーにロードされる共有ライブラリを作成します。

また、demoには64ビット・クライアント実行可能ファイル作成用のdemo_rdbms64.mkもあります。このMakefileでも、demo_rdbms.mkを使用して、データベース・サーバーにロードされる外部プロシージャ・コール用共有ライブラリを作成します。

ociucb.mkは、demoにあるコールバック共有ライブラリ作成用Makefileです。このMakefileにも、使用方法に関するコメントが含まれています。

OCIプログラム構造

OCIアプリケーションの全般的な目標は、マルチ・ユーザーのために稼働することです。N層構造では、マルチ・ユーザーがクライアント・アプリケーションにHTTP要求を送信します。クライアント・アプリケーションでは、データ交換やデータ処理など、いくつかのデータ操作を実行する必要があります。

OCIでは、次のプログラム基本構造を使用しています。

  1. OCIプログラミング環境およびスレッドの初期化

  2. 必要なハンドルの割当て、およびサーバー接続とユーザー・セッションの確立

  3. サーバー上でのSQL文の実行、データベース・サーバーとの間でのデータ交換、必要なアプリケーション・データ処理の実行

  4. プリコンパイルされたSQL文の実行、または新規に実行する文の準備

  5. ユーザー・セッションおよびサーバー接続の終了

  6. フリー・ハンドル

図2-1「基本的なOCIプログラムの流れ」は、OCIアプリケーションのステップの流れを示しています。各ステップの詳細は、「OCIプログラミング・ステップ」の項を参照してください。

図2-1基本的なOCIプログラムの流れ

図2-1の説明は次にあります
「図2-1基本的なOCIプログラムの流れ」の説明

図およびステップ・リストは、OCIプログラミングのステップを簡潔に表したものです。さらに、プログラムの機能性に応じて様々なバリエーションが考えられます。複数セッションおよび複数トランザクションの管理やオブジェクトの使用など、より高度な機能が組み込まれるOCIアプリケーションには、追加のステップが必要です。

すべてのOCIファンクション・コールは、ある環境のコンテキスト内で実行されます。1つのOCIプロセス内に複数の環境が存在することが可能です。環境でプロセスレベルの初期化が必要になった場合には、自動的に実行されます。


注意:


OCIアプリケーションには、アクティブな接続および文を2つ以上含めることができます。


関連項目:


オブジェクトへのアクセスおよびその操作の詳細は、第11章「OCIオブジェクト・リレーショナル・プログラミング」およびそれ以降の章を参照してください。

OCIデータ構造

ハンドルと記述子は、OCIアプリケーションで定義された不透明なデータ構造体です。ハンドルと記述子は、特定の割当てコールによって直接割り当てるか、あるいはOCI関数を使用して暗黙的に割り当てることができます。


7.xアップグレードの注意:


リリース7.x OCIのアプリケーション作成の経験を持つプログラマは、大部分のOCIコールに使用されているこれらの新しいデータ構造に慣れる必要があります。

ハンドルおよび記述子を使用して、データ、接続またはアプリケーション動作に関係する情報を格納します。ハンドルについては、次の項で詳しく定義します。


関連項目:


記述子の詳細は、「OCI記述子」の項を参照してください。

ハンドル

ほとんどの場合、OCIコールのパラメータ・リストには、ハンドルが1つ以上含まれています。ハンドルとは、OCIライブラリによって割り当てられる記憶領域を指す不透明なポインタです。ハンドルを使用すると、コンテキストや接続に関する情報(環境コンテキスト・ハンドルやサービス・コンテキスト・ハンドルなど)を格納できます。またOCI関数やデータに関する情報(エラー・ハンドルや記述ハンドルなど)を格納する場合もあります。つまり、ハンドルを使用するとアプリケーションではなくライブラリでこのデータを維持できるため、プログラミングが簡単になります。

ほとんどのOCIアプリケーションでは、ハンドルに格納されている情報へのアクセスが必要となります。この情報にアクセスして設定するには、属性の入手および設定のためのOCIコールであるOCIAttrGet()およびOCIAttrSet()を使用します。

表2-1は、OCI用に定義されているハンドルを示しています。それぞれのハンドル・タイプについて、OCIコールでハンドル・タイプを識別するために使用される、Cデータ型およびハンドル・タイプ定数をリストしています。

表2-1 OCIハンドル・タイプ

説明 Cデータ型 ハンドル・タイプ定数

OCI環境ハンドル

OCIEnv

OCI_HTYPE_ENV

OCIエラー・ハンドル

OCIError

OCI_HTYPE_ERROR

OCIサービス・コンテキスト・ハンドル

OCISvcCtx

OCI_HTYPE_SVCCTX

OCI文ハンドル

OCIStmt

OCI_HTYPE_STMT

OCIバインド・ハンドル

OCIBind

OCI_HTYPE_BIND

OCI定義ハンドル

OCIDefine

OCI_HTYPE_DEFINE

OCI記述ハンドル

OCIDescribe

OCI_HTYPE_DESCRIBE

OCIサーバー・ハンドル

OCIServer

OCI_HTYPE_SERVER

OCIユーザー・セッション・ハンドル

OCISession

OCI_HTYPE_SESSION

OCI認証情報ハンドル

OCIAuthInfo

OCI_HTYPE_AUTHINFO

OCI接続プール・ハンドル

OCICPool

OCI_HTYPE_CPOOL

OCIセッション・プール・ハンドル

OCISPool

OCI_HTYPE_SPOOL

OCIトランザクション・ハンドル

OCITrans

OCI_HTYPE_TRANS

OCI複合オブジェクト検索(COR)ハンドル

OCIComplexObject

OCI_HTYPE_COMPLEXOBJECT

OCIスレッド・ハンドル

OCIThreadHandle

該当なし

OCIサブスクリプション・ハンドル

OCISubscription

OCI_HTYPE_SUBSCRIPTION

OCIダイレクト・パス・コンテキスト・ハンドル

OCIDirPathCtx

OCI_HTYPE_DIRPATH_CTX

OCIダイレクト・パス関数コンテキスト・ハンドル

OCIDirPathFuncCtx

OCI_HTYPE_DIRPATH_FN_CTX

OCIダイレクト・パス列配列ハンドル

OCIDirPathColArray

OCI_HTYPE_DIRPATH_COLUMN_ARRAY

OCIダイレクト・パス・ストリーム・ハンドル

OCIDirPathStream

OCI_HTYPE_DIRPATH_STREAM

OCIプロセス・ハンドル

OCIProcess

OCI_HTYPE_PROC

OCI管理ハンドル

OCIAdmin

OCI_HTYPE_ADMIN

OCI HAイベント・ハンドル

OCIEvent

該当なし


ハンドルの割当てと解放

アプリケーションでは、すべてのハンドル(バインド・ハンドル、定義ハンドルおよびスレッド・ハンドルは除く)が、特定の環境ハンドルに対して割り当てられます。環境ハンドルをパラメータの1つとして、ハンドル割当てコールに渡します。こうして、割り当てられたハンドルは、その特定の環境に固有のものとなります。

バインド・ハンドルおよび定義ハンドルは、文ハンドルを親として割り当てられ、そのハンドルによって表される文についての情報を含みます。


注意:


バインド・ハンドルおよび定義ハンドルは、OCIライブラリによって暗黙的に割り当てられるため、ユーザーによる割当ては不要です。

環境ハンドルはOCIEnvCreate()またはOCIEnvNlsCreate()のコールによって割り当てられ、初期化されます。このコールのいずれかは、すべてのOCIアプリケーションで必要です。

ユーザー割当てハンドルは、すべてOCIハンドル割当てコールOCIHandleAlloc()によって初期化されます。

ハンドルには、セッション・ハンドル、ダイレクト・パス・コンテキスト・ハンドル、スレッド・ハンドル、CORハンドル、サブスクリプション・ハンドル、記述ハンドル、文ハンドル、サービス・コンテキスト・ハンドル、エラー・ハンドル、サーバー・ハンドル、接続プール・ハンドル、イベント・ハンドルおよび管理ハンドルなど様々なタイプがあります。

スレッド・ハンドルは、OCIThreadHndInit()コールによって割り当てられます。

アプリケーションは、ハンドルが不要になった時点で全ハンドルを解放する必要があります。すべてのハンドルはOCIHandleFree()関数によって解放されます。


注意:


親ハンドルが解放されると、それに対応付けられた子ハンドルもすべて解放され、それ以降使用できなくなります。たとえば、文ハンドルが解放されると、それに関連付けられたバインド・ハンドルおよび定義ハンドルも解放されます。

ハンドルにより、グローバル変数を使用する必要性が少なくなります。また、エラー・レポートが簡単になります。エラー・ハンドルは、エラーと診断情報を戻すために使用します。


関連項目:


OCIハンドルの割当てと使用方法を示したコード例は、付録B「OCIデモ・プログラム」のプログラム例を参照してください。

環境ハンドル

環境ハンドルは、すべてのOCI関数をコールするコンテキストを定義します。各環境ハンドルにはメモリー・キャッシュがあり、これによってメモリー・アクセスが高速になります。環境ハンドルに基づくメモリーの割当ては、このキャッシュで行われます。キャッシュへのアクセスは、複数のスレッドが同じ環境ハンドルに基づいてメモリーの割当てを試行する場合にシリアライズされます。複数のスレッドで単一の環境ハンドルを共有する場合、スレッドはキャッシュへのアクセスをブロックすることがあります。

環境ハンドルは、parentパラメータとしてOCIHandleAlloc()コールに渡され、その他のすべてのハンドル・タイプを割り当てます。バインド・ハンドルと定義ハンドルは、暗黙的に割り当てられます。

エラー・ハンドル

エラー・ハンドルは、ほとんどのOCIコールにパラメータとして渡されます。エラー・ハンドルは、OCI操作中に発生したエラーについての情報をメンテナンスします。コールでエラーが発生した場合、エラー・ハンドルをOCIErrorGet()に渡して、発生したエラーに関する追加情報を取得することができます。

ほとんどのOCIコールではパラメータの1つとしてエラー・ハンドルが必要であるため、エラー・ハンドルの割当ては、OCIアプリケーションの最初のステップです。

サービス・コンテキスト・ハンドルとそれに対応付けられたハンドル

サービス・コンテキスト・ハンドルは、サーバーに対するOCIコールの操作コンテキストを決定する属性を定義します。サービス・コンテキストには、サーバー接続、ユーザー・セッションおよびトランザクションを示す3つのハンドルが属性として含まれています。これらの属性を、図2-2「サービス・コンテキストのコンポーネント」に示します。

図2-2 サービス・コンテキストのコンポーネント

図2-2の説明は次にあります
「図2-2 サービス・コンテキストのコンポーネント」の説明

  • サーバー・ハンドルは、データベースとの接続を識別します。これは、接続指向のトランスポート・メカニズムによって物理接続に変換されます。

  • ユーザー・セッション・ハンドルは、ユーザーのロールと権限(ユーザーのセキュリティ・ドメインとも呼ばれる)およびコールを実行するための操作コンテキストを定義します。

  • トランザクション・ハンドルは、SQL操作を実行するトランザクションを定義します。トランザクション・コンテキストには、フェッチ状態やパッケージのインスタンス化などの、ユーザー・セッション状態の情報が含まれています。

この方法によるサービス・コンテキストの分析は、拡張性を提供し、プログラマは、洗練された複数層のアプリケーションとトランザクション処理(TP)モニターを作成して、複数のアプリケーション・サーバーと異なるトランザクション・コンテキスト上の複数のユーザーの要求を実行できます。

サービス・コンテキスト・ハンドルを使用する際は、その前にOCIHandleAlloc()またはOCILogon()によって、割当てと初期化を行う必要があります。サービス・コンテキスト・ハンドルは、OCIHandleAlloc()によって明示的に割り当てられます。また、サーバー・ハンドル、セッション・ハンドルおよびトランザクション・ハンドルでは、OCIAttrSet()を使用して初期化できます。サービス・コンテキスト・ハンドルがOCILogon()によって暗黙的に割り当てられている場合には、すでに初期化されています。

データベース接続ごとに常時シングル・ユーザー・セッションのみをメンテナンスするアプリケーションでは、OCILogon()をコールして、初期化されたサービス・コンテキスト・ハンドルを取得できます。

より複雑なセッション管理を必要とするアプリケーションでは、サービス・コンテキストを明示的に割り当てる必要があります。また、サーバー・ハンドルおよびユーザー・セッション・ハンドルは、サービス・コンテキストに明示的に設定する必要があります。OCIServerAttach()コールとOCISessionBegin()コールは、サーバー・ハンドルとユーザー・セッション・ハンドルを初期化します。

グローバル・トランザクションの場合、あるいはセッションに対してアクティブなトランザクションが複数存在する場合、アプリケーションではトランザクションを明示的に定義するのみです。また、アプリケーションでは、データベースの内容を変更した際にOCIによって自動的に作成された暗黙的トランザクションを正しく処理できます。


関連項目:


文ハンドル、バインド・ハンドルおよび定義ハンドル

文ハンドルは、SQL文またはPL/SQL文と、それぞれに関連付けられた属性を識別するコンテキストです。これについて図2-3「文ハンドル」で示しています。

入力バインド変数および出力バインド変数に関する情報は、バインド・ハンドルに格納されます。OCIライブラリでは、OCIBindByName()またはOCIBindByPos()関数でバインドされた各プレースホルダのバインド・ハンドルが割り当てられます。ユーザーはバインド・ハンドルを割り当てることはできません。バインド・ハンドルは、バインド・コールによって暗黙的に割り当てられます。

問合せ(select文)でフェッチされて戻されたデータは、定義ハンドルの指定に従って変換および格納されます。またOCIライブラリによって、OCIDefineByPos()で定義された各出力変数の定義ハンドルが割り当てられます。ユーザーは定義ハンドルを割り当てることはできません。定義ハンドルは、定義コールによって暗黙的に割り当てられます。

バインド・ハンドルおよび定義ハンドルはOCIライブラリによって暗黙的に割り当てられ、バインド操作または定義操作が繰り返されると、透過的に再利用されます。バインド・ハンドルまたは定義ハンドルの実際の値は、バインドおよび定義に関する章で説明する拡張バインド操作または定義操作のためにアプリケーションで必要とされます。ハンドルが解放されるのは、文ハンドルが解放されたとき、または文ハンドルに新しい文が準備されたときです。バインド・ハンドルまたは定義ハンドルを明示的に割り当てると、メモリー・リークが発生する可能性があります。バインド・ハンドルまたは定義ハンドルを明示的に解放すると、プログラムが異常終了する可能性があります。

記述ハンドル

記述ハンドルは、OCI記述コールであるOCIDescribeAny()によって使用されます。このコールは、ファンクションやプロシージャなどデータベース内のスキーマ・オブジェクトに関する情報を取得します。このコールでは、記述されているオブジェクトに関する情報とともに、パラメータの1つとして記述ハンドルが使用されます。コールが完了すると、記述ハンドルには、そのオブジェクトに関する情報が含まれています。OCIアプリケーションでは、パラメータ記述子の属性を通して記述情報を取得します。


関連項目:


OCIDescribeAny()関数の使用方法の詳細は、第6章「スキーマ・メタデータの記述」を参照してください。

複合オブジェクト検索ハンドル

複合オブジェクト検索(COR)ハンドルは、Oracleデータベース・サーバー内のオブジェクトを操作する一部のOCIアプリケーションによって使用されます。このハンドルには、他のオブジェクトによって参照されるオブジェクトの検索について指示するCOR記述子が含まれています。

スレッド・ハンドル

マルチスレッド・アプリケーションで使用されているスレッド・ハンドルの詳細は、次を参照してください。

サブスクリプション・ハンドル

サブスクリプション・ハンドルは、登録およびサブスクライブを行うOCIクライアント・アプリケーションによって使用され、データベース・イベントまたはAQネームスペース内のイベントの通知を受け取るために使用されます。サブスクリプション・ハンドルは、クライアントからの登録に関するすべての情報をカプセル化します。

ダイレクト・パス・ハンドル

ダイレクト・パス・ハンドルは、Oracleデータベース・サーバー内でダイレクト・パス・ロード・エンジンを利用するOCIアプリケーションに必要です。ダイレクト・パス・ロード・インタフェースを使用して、アプリケーションからOracleサーバーのダイレクト・ブロック・フォーマッタにアクセスできます。図2-4「ダイレクト・パス・ハンドル」では、各種ダイレクト・パス・ハンドルを示しています。

図2-4 ダイレクト・パス・ハンドル

図2-4の説明は次にあります
「図2-4 ダイレクト・パス・ハンドル」の説明

接続プール・ハンドル

接続プール・ハンドルは、特定のOCI関数をコールして物理接続を仮想接続にプールするアプリケーションで使用されます。

ハンドル属性

すべてのOCIハンドルには、そのハンドルに格納されたデータを表す属性があります。ハンドル属性は、属性取得コールOCIAttrGet()を使用して読み取ることができます。また、属性設定コールOCIAttrSet()を使用して変更することもできます。

たとえば、次の文ではOCI_ATTR_USERNAME属性に書き込むことで、セッション・ハンドルにユーザー名を設定しています。

text username[] = "hr";
err = OCIAttrSet ((void *) mysessp, OCI_HTYPE_SESSION, (void *)username,
      (ub4) strlen((char *)username), OCI_ATTR_USERNAME, (OCIError *) myerrhp);

コールの前に特定のハンドル属性を設定することが必要なOCI関数もあります。たとえば、ユーザーのログイン・セッションを確立するためにOCISessionBegin()をコールする場合は、コールの実行前にユーザー名とパスワードをユーザー・セッション・ハンドルに設定する必要があります。

完了後、ハンドル属性に有用なデータを戻すOCI関数もあります。たとえば、OCIStmtExecute()をコールしてSQL問合せを実行した場合は、選択リスト項目に関する記述情報が文ハンドルに戻されます。

ub4 parmcnt;
/* get the number of columns in the select list */
err = OCIAttrGet ((void  *)stmhp, (ub4)OCI_HTYPE_STMT, (void  *)
         &parmcnt, (ub4 *) 0, (ub4)OCI_ATTR_PARAM_COUNT, errhp);

関連項目:


OCI記述子

OCIの記述子およびロケータは、データ固有の情報をメンテナンスする不透明なデータ構造体です。これらの記述子とロケータ、Cデータ型および、OCI型の記述子をOCIDescriptorAlloc()のコール内で割り当てるために使用するOCI型定数を、表2-2に示します。OCIDescriptorFree()関数は、記述子とロケータを解放します。OCIArrayDescriptorAlloc()関数およびOCIArrayDescriptorFree()関数も参照してください。

表2-2 記述子タイプ

説明 Cデータ型 OCI型定数

スナップショット記述子

OCISnapshot

OCI_DTYPE_SNAP

結果セット記述子

OCIResult

OCI_DTYPE_RSET

LOBデータ型ロケータ

OCILobLocator

OCI_DTYPE_LOB

BFILEデータ型ロケータ

OCILobLocator

OCI_DTYPE_FILE

読取り専用パラメータ記述子

OCIParam

OCI_DTYPE_PARAM

ROWID記述子

OCIRowid

OCI_DTYPE_ROWID

ANSI DATE記述子

OCIDateTime

OCI_DTYPE_DATE

TIMESTAMP記述子

OCIDateTime

OCI_DTYPE_TIMESTAMP

TIMESTAMP WITH TIME ZONE記述子

OCIDateTime

OCI_DTYPE_TIMESTAMP_TZ

TIMESTAMP WITH LOCAL TIME ZONE記述子

OCIDateTime

OCI_DTYPE_TIMESTAMP_LTZ

INTERVAL YEAR TO MONTH記述子

OCIInterval

OCI_DTYPE_INTERVAL_YM

INTERVAL DAY TO SECOND記述子

OCIInterval

OCI_DTYPE_INTERVAL_DS

ユーザー・コールバック記述子

OCIUcb

OCI_DTYPE_UCB

登録要求でのデータベース・サーバーの識別名

OCIServerDNs

OCI_DTYPE_SRVDN

複合オブジェクト記述子

OCIComplexObjectComp

OCI_DTYPE_COMPLEXOBJECTCOMP

アドバンスト・キューイング・エンキュー・オプション

OCIAQEnqOptions

OCI_DTYPE_AQENQ_OPTIONS

アドバンスト・キューイング・デキュー・オプション

OCIAQDeqOptions

OCI_DTYPE_AQDEQ_OPTIONS

アドバンスト・キューイング・メッセージ・プロパティ

OCIAQMsgProperties

OCI_DTYPE_AQMSG_PROPERTIES

アドバンスト・キューイング・エージェント

OCIAQAgent

OCI_DTYPE_AQAGENT

アドバンスト・キューイング通知

OCIAQNotify

OCI_DTYPE_AQNFY

アドバンスト・キューイング・リスニング・オプション

OCIAQListenOpts

OCI_DTYPE_AQLIS_OPTIONS

アドバンスト・キューイング・メッセージ・プロパティ

OCIAQLisMsgProps

OCI_DTYPE_AQLIS_MSG_PROPERTIES

変更通知

なし

OCI_DTYPE_CHDES

表の変更

なし

OCI_DTYPE_TABLE_CHDES

行の変更

なし

OCI_DTYPE_ROW_CHDES



注意:


OCILobLocatorに対するC型は1つのみですが、このロケータは内部LOBおよび外部LOBに対しては異なるOCI型定数で割り当てられます。後述のLOBロケータの項で、この違いについて説明します。

各記述子型の主な用途は次のとおりです。各記述子型については、後述の項で説明します。

スナップショット記述子

スナップショット記述子は、OCIStmtExecute()のコールを実行するためのオプション・パラメータです。この記述子は、特定のデータベース・スナップショットに対する問合せが実行されることを示します。データベース・スナップショットは、ある特定の時点におけるデータベースの状態を表します。

スナップショット記述子は、OCIDescriptorAlloc()のコールで、OCI_DTYPE_SNAPtypeパラメータとして渡すことによって割り当てられます。


関連項目:


OCIStmtExecute()およびデータベース・スナップショットの詳細は、「実行スナップショット」の項を参照してください。

LOBおよびBFILEロケータ

ラージ・オブジェクト(LOB)は、バイナリ(BLOB)または文字(CLOB)データを保持できるOracleデータ型です。データベース内では、LOBロケータと呼ばれる不透明なデータ構造が、データベース行のLOB列、あるいはオブジェクトのLOB属性の位置に格納されます。このロケータは、別の位置に格納されている実際のLOB値を指すポインタとして機能します。


注意:


アプリケーションによって、LOBロケータを使用する場合と使用しない場合があります。LOBのデータ・インタフェースを使用できますが、このインタフェースはLOBロケータを必要としません。このインタフェースでは、CLOB列の文字データ、またはBLOB列のRAWデータをバインドまたは定義できます。

OCI LOBロケータは、LOB(BLOBまたはCLOB)またはFILE(BFILE)に対するOCI操作の実行に使用されます。OCILobXXX関数では、LOB値のかわりにLOBロケータがパラメータとして使用されます。OCI LOB関数では、パラメータとして実際のLOBデータは使用されません。この関数では、パラメータとしてLOBロケータを使用し、LOBロケータによって参照されるLOBデータを操作します。

LOBロケータは、OCIDescriptorAlloc()のコールで、BLOBまたはCLOBtypeパラメータとしてのOCI_DTYPE_LOB、およびBFILEOCI_DTYPE_FILEを渡すことによって割り当てられます。


注意:


これらの2つのLOBロケータ型は交換できません。BLOBCLOBをバインドまたは定義するとき、アプリケーションでは、OCI_DTYPE_LOBを使用してロケータが適切に割り当てられるようにする必要があります。同様に、BFILEをバインドまたは定義するとき、アプリケーションでは、OCI_DTYPE_FILEを使用してロケータが割り当てられるようにする必要があります。

OCIアプリケーションでは、選択リストの要素としてLOB列または属性を含むSQL文を発行することによって、サーバーからLOBロケータを取り出せます。その場合、アプリケーションは最初にLOBロケータを割り当て、次にそれを使用して出力変数を定義します。同様に、LOBロケータは、SQL文でLOBとプレースホルダとの間の関連付けを行うバインド操作の一部として使用できます。

パラメータ記述子

OCIアプリケーションは、パラメータ記述子を使用して、選択リスト列またはスキーマ・オブジェクトについての情報を取得します。この情報は、記述操作を通して取得されます。

このパラメータ記述子は、OCIDescriptorAlloc()を使用して割り当てられることのない唯一の記述子タイプです。パラメータ記述子は、OCIParamGet()コールを使用してパラメータの位置を指定することによって、記述ハンドル、文ハンドル、または複合オブジェクト検索ハンドルの属性としてのみ取得できます。


関連項目:


パラメータ記述子の取得と使用の詳細は、第6章「スキーマ・メタデータの記述」および「選択リスト項目の記述」を参照してください。

ROWID記述子

ROWID記述子(OCIRowid)は、Oracle ROWIDを取り出して使用する必要があるアプリケーションで使用されます。リリース8.x以上のOCIを使用してROWIDを操作するために、アプリケーションではSQL選択リスト内のROWIDの位置に対応するROWID記述子を定義し、その記述子内のROWIDを検索できます。この同じ記述子を、後でINSERT文またはWHERE句の入力変数にバインドできます。

また、文の実行後に文ハンドルでOCIAttrGet()を使用し、ROWIDを記述子にリダイレクトできます。

日付、日時および時間隔の記述子

これらの記述子は、日付、日時または時間隔データ型(OCIDateOCIDateTimeおよびOCIInterval)を使用するアプリケーションで使用されます。これらの記述子は、バインドおよび定義で使用され、メモリーを割り当てたり解放する関数のOCIDescAlloc()およびOCIDescFree()にパラメータとして渡されます。


関連項目:


複合オブジェクト記述子

オブジェクトの処理時に、複合オブジェクト検索(COR)を使用すると、アプリケーションのパフォーマンスが向上する場合があります。


関連項目:


複合オブジェクト記述子およびその使用方法の詳細は、「複合オブジェクト検索」を参照してください。

アドバンスト・キューイング記述子

Oracle AQは、Oracleサーバーと統合されたメッセージ・キューイングです。

ユーザー・メモリーの割当て

OCIDescriptorAlloc()コールには、そのパラメータ・リストにxtramem_szパラメータが含まれています。このパラメータは、記述子またはロケータとともに割り当てるユーザー・メモリー量を指定するために使用します。

通常、アプリケーションは、このパラメータを使用して、記述子またはロケータと同じ存続期間を持つアプリケーション定義の構造体を割り当てます。この構造体は、アプリケーション・ブックキーピングまたはコンテキスト情報の格納に使用できます。

xtramem_szパラメータを使用すると、アプリケーションでは、各記述子またはロケータを割り当てたり、割当て解除するたびに、メモリーを明示的に割り当てたり、割当て解除する必要がありません。メモリーは記述子またはロケータとともに割り当てられるため、記述子またはロケータを解放すると(OCIDescriptorFree()により)、ユーザーのデータ構造も解放されます。

OCIHandleAlloc()コールには、ハンドルと同じ存続期間を持つユーザー・メモリーを割り当てるための同様のパラメータがあります。

OCIEnvCreate()コールおよびOCIEnvInit()コールには、環境ハンドルと同じ存続期間を持つユーザー・メモリーを割り当てるための同様のパラメータがあります。

OCIプログラミング・ステップ

この後の各項では、OCIアプリケーションを開発する各ステップについて詳しく説明します。いくつかのステップは、オプションです。たとえば、文が問合せでない場合には、選択リスト項目を記述または定義する必要はありません。


関連項目:


次の各項では、OCIのアプリケーションで必要なステップについて説明します。

また、OCI関数のいずれか、またはすべてのステップ間で、アプリケーション固有の処理も発生します。

OCI環境の初期化

この項では、OCI環境を初期化してサーバーとの接続を確立し、ユーザーがデータベースに対してアクションを実行できるように許可する方法を説明します。

次の3つの項では、OCI環境を初期化するための3つの主要なステップについて説明します。

OCI環境の作成

各OCIファンクション・コールは、OCIEnvCreate()コールで作成された環境のコンテキスト内で実行されます。このコールは、他のOCIコールの実行よりも先に行う必要があります。唯一の例外は、OCI共有モードのプロセスレベルの属性を設定する場合です。

OCIEnvCreate()modeパラメータは、OCIライブラリ関数をコールするアプリケーションが次のことを行うかどうか指定します。

  • スレッド化環境での実行(mode = OCI_THREADED

  • オブジェクトの使用(mode = OCI_OBJECT)AQサブスクリプションの登録での使用

  • サブスクリプションの使用(mode = OCI_EVENTS

これらのモードは、環境ごとに設定できます。

アプリケーションがオブジェクトのバインドおよび定義を行う場合、またはOCIのオブジェクト・ナビゲーション・コールを使用する場合は、オブジェクト・モードでの初期化が必要です。また、アプリケーションでこれらの機能をすべて使用しないようにしたり(mode = OCI_DEFAULT)、縦線で区切って組み合せて使用することもできます。たとえば、mode = (OCI_THREADED | OCI_OBJECT)を指定すると、アプリケーションはスレッド化環境で動作し、オブジェクトを使用します。

OCI環境ごとにユーザー定義のメモリー管理関数を指定できます。

ハンドルおよび記述子の割当て

Oracleは、ハンドルと記述子を割り当てたり割当て解除するためのOCI関数を提供します。ハンドルは、OCIHandleAlloc()を使用して割り当てた後、OCIコールに渡す必要があります(OCIBindByPos()のように、OCIコールがユーザーにかわってハンドルを割り当てる場合は除きます)。

OCIHandleAlloc() を使用して、表2-1「OCIハンドル・タイプ」にリストされた種類のハンドルを割当てできます。アプリケーションの機能に応じて、これらのハンドルのいくつかまたはすべてを割り当ててください。

アプリケーションの初期化、接続およびセッション作成

アプリケーションでは、OCIEnvNlsCreate()をコールしてOCI環境ハンドルを初期化する必要があります。既存のアプリケーションで、OCIEnvCreate()が使用されていた可能性があります。

アプリケーションで、このステップに従ってサーバー接続を確立し、ユーザー・セッションを開始する場合、いくつかのオプションがあります。


注意:


OCIInitialize()およびOCIEnvInit()コールのかわりに、OCIEnvCreate()またはOCIEnvNlsCreate()を使用する必要があります。OCIInitialize()およびOCIEnvInit()コールは、下位互換性を保つためにサポートされています。

シングル・ユーザー、単一接続

このオプションは、単純化されたログイン方法です。データベース接続ごとに常時シングル・ユーザー・セッションのみをメンテナンスする場合に使用できます。

アプリケーションからOCILogon2()をコールすると、OCIライブラリは、渡されたサービス・コンテキスト・ハンドルを初期化し、次に、要求を行ったユーザーが指定したサーバーへの接続を作成します。

次の例は、シングル・ユーザー・セッション(ユーザー名hr、パスワードhrおよびデータベースoracledb)を開始するためのOCILogon2()のコールを示しています。

OCILogon2(envhp, errhp, &svchp, (text *)"hr", (ub4)strlen("hr"), (text *)"hr",
          (ub4)strlen("hr"), (text *)"oracledb", (ub4)strlen("oracledb"),
          OCI_DEFAULT);

このコールのパラメータには、接続を確立するために使用するサービス・コンテキスト・ハンドル(初期化済)、ユーザー名、ユーザーのパスワードおよびデータベース名を含めることができます。このコールでは、最後のパラメータmodeOCI_DEFAULTに設定することで、旧OCILogon()コールと同じ結果が得られます。新しいアプリケーションでは、OCILogon2()を使用します。この関数によって、サーバー・ハンドルおよびユーザー・セッション・ハンドルが暗黙的に割り当てられます。

アプリケーションがこのログイン方法を使用する場合、サービス・コンテキスト、サーバーおよびユーザー・セッション・ハンドルはすべて読取り専用となります。つまり、OCIAttrSet()コールによってサービス・コンテキスト・ハンドルの該当する属性を変更することにより、アプリケーションがセッションまたはトランザクションを切り替えることはできません。

アプリケーションでOCILogon2()を使用してセッションおよび認可を初期化した場合は、OCILogoff()を使用してそれらを終了する必要があります。


注意:


この機能を簡単に示すため、この例ではデプロイされたシステムが通常使用するパスワード管理手法は実行していません。 本番環境では、Oracle Databaseパスワード管理ガイドラインに従い、サンプルのアカウントを無効にしてください。 パスワード管理ガイドラインおよび他のセキュリティに関する推奨事項については、『Oracle Databaseセキュリティ・ガイド』を参照してください。

プロキシ経由のクライアント・アクセス

通常、プロキシ認証は、ファイアウォールなどの中間層のある環境で採用されるプロセスです。そのような環境では、エンド・ユーザーが中間層で認証され、この中間層がそのユーザーのかわりに—ユーザーのプロキシとして、データベースで認証されます。中間層はプロキシ・ユーザーとしてデータベースにログインします。プロキシ・ユーザーは識別情報を切り替えることができ、データベースにログインした後、エンド・ユーザーの識別情報に切り替えることができます。プロキシ・ユーザーは、特定のエンド・ユーザーに対する適切な権限を使用して、エンド・ユーザーのかわりに操作を実行できます。


注意:


Oracle 11gのリリース1では、受入れ可能なパスワードの基準が大幅に上げられ、セキュリティが向上しました。この項で示すパスワードの例は誤りです。パスワードには8文字以上使用する必要があります。『Oracle Databaseセキュリティ・ガイド』のパスワード保護のガイドラインに関する項で、追加のガイドラインを示しています。『Oracle Databaseセキュリティ・ガイド』を参照してください。

データベース・ユーザーのプロキシは、OCIと次のBNF構文を持つALTER USER文でサポートされます。

ALTER USER <targetuser> GRANT CONNECT THROUGH <proxy> [AUTHENTICATION REQUIRED];

ALTER USER文は、アプリケーションで一度のみ使用されます。以降は、何回でも接続できます。OCIでは、接続文字列または関数OCIAttrSet()(パラメータOCI_ATTR_PROXY_CLIENT付き)を使用できます。

プロキシの切替えが行われると、現在接続しているユーザーがプロキシのターゲット・ユーザーになります。元のユーザーの識別情報は、権限の計算対象としては使用されません。元のユーザーはローカル・ユーザーまたは外部ユーザーになります。

次の例は、OCIAttrSet()(セッション・ハンドルの属性OCI_ATTR_USERNAMEを渡す)とともに、OCILogon2()mode = OCI_DEFAULTを設定)、OCILogon()OCISessionBegin()などの関数内で使用できる接続文字列を示しています。

  1. ローカル・ユーザーを別のローカル・ユーザーの代理にする場合

    DilbertとJoeの2人は、それぞれがローカル・データベース・ユーザーです。DilbertをJoeの代理にするには、次のSQL文を使用します。

    ALTER USER joe GRANT CONNECT THROUGH dilbert;
    

    ユーザー名dilbertjoeの代理にするには、接続文字列を次のようにします(dilbertのパスワードはtiger123)。

    dilbert[joe]/tiger123@db1
    

    [ と ] は、実際に接続文字列に入力します。

  2. ローカル・ユーザーを別のローカル・ユーザーの代理とし、かつ各ユーザー名を引用符で囲む必要がある場合

    "Dilbert"と"Joe"の2人は、それぞれがローカル・データベース・ユーザーです。これらの名前は大/小文字を区別し、引用符で囲む必要があります。"Dilbert"を"Joe"の代理にするには、次のSQL文を使用します。

    ALTER USER "Joe" GRANT CONNECT THROUGH "Dilbert";
    

    "Dilbert"を"Joe"の代理にするには、接続文字列を次のようにします(文字 " も含めます)。

    "Dilbert"["Joe"]/tiger123@db1
    
  3. ローカル・ユーザーdilbert[mybert ]がデータベースに接続する場合

    データベース"dilbert[mybert]"にユーザーが存在し、このユーザーのデータベース接続方法は次のとおりです([ と ] は実際に接続文字列に入力します)。

    "dilbert[mybert]"/tiger123
    
    rem the user was already created this way:
    rem CREATE USER "dilbert[mybert]" IDENTIFIED BY tiger123;
    
  4. ローカル・ユーザーを別のローカル・ユーザーの代理にし、かつユーザー名に [ ] を含める場合

    dilbert[mybert]およびjoe[myjoe]の2人は、文字 [ と ] を含んだデータベース・ユーザーです。dilbert[mybert]を[myjoe]の代理にするには、接続文を次のようにします。

    "dilbert[mybert]"["joe[myjoe]"]/tiger123
    
  5. ターゲット・ユーザー名を設定するには、ALTER USER文の後、OCIプログラムを使用して、その中のOCIAttrSet()によって属性OCI_ATTR_PROXY_CLIENTおよびプロキシdilbertを設定します。たとえば、次のようにします。

    ALTER USER joe GRANT CONNECT THROUGH dilbert;
    

    プログラム内で次の各文を使用して複数回接続を行います。

    OCIAttrSet(session, OCI_HTYPE_SESSION, (void  *)"dilbert",
               (ub4)strlen("dilbert"), OCI_ATTR_USERNAME,
               error_handle);
    OCIAttrSet(session, OCI_HTYPE_SESSION, (void  *)"tiger123",
               (ub4)strlen("tiger123"), OCI_ATTR_PASSWORD,
               error_handle);
    OCIAttrSet(session, OCI_HTYPE_SESSION, (void  *)"joe",
               (ub4)strlen("joe"), OCI_ATTR_PROXY_CLIENT,
               error_handle);
    

関連項目:


プロキシ経由のクライアント・アクセスにおける互換性の問題

この機能はリリース10.2で導入されたため、10.2より前のクライアントはこの機能を備えていません。新しいクライアントが10.2より前のデータベースでこの機能を使用すると、接続は失敗し、データベースのリリース・レベルのチェック後にクライアントがエラーを戻します。

プロキシを介さない複数のセッションまたは接続

このオプションでは、明示的なアタッチ・コールおよびセッション開始コールを使用して、データベース接続で複数のユーザー・セッションおよび接続を作成します。サーバーにアタッチし、セッションを開始するための具体的なコールは、次のとおりです。

  • OCIServerAttach()− OCI操作用のデータ・サーバーにアクセスするためのアクセス・パスを作成します。

  • OCISessionBegin()− 特定のサーバーに対するユーザーのセッションを確立します。ユーザーがサーバーに対する操作を実行するには、このコールが必須です。

異なるサービス・コンテキスト・ハンドルおよびセッション・コンテキスト・ハンドルを使用するOCISessionBegin()への後続コールは、前のユーザーをログオフするため、エラーを引き起こします。移行不可能な2つの同時セッションを実行するには、2番目のOCISessionBegin()コールに、同じサービス・コンテキスト・ハンドルおよび新しいセッション・コンテキスト・ハンドルを使用する必要があります。

これらのコールにより、データベースに対してSQL文およびPL/SQL文を実行できる操作環境が設定されます。


関連項目:


OCI環境の作成および初期化の例

OCI環境の作成および初期化の使用例を次に示します。

  • サーバー・コンテキストを作成し、それをサービス・ハンドルに設定します。

  • 次に、ユーザー・セッション・ハンドルを作成し、データベース・ユーザー名とパスワードを使用してそれを初期化します。

  • 簡潔にするため、エラー・チェックは含まれていません。

#include <oci.h>
...
main()
{
...
OCIEnv     *myenvhp;    /* the environment handle */
OCIServer  *mysrvhp;    /* the server handle */
OCIError   *myerrhp;    /* the error handle */
OCISession *myusrhp;    /* user session handle */
OCISvcCtx  *mysvchp;    /* the  service handle */
...
/* initialize the mode to be the threaded and object environment */
(void) OCIEnvCreate(&myenvhp, OCI_THREADED|OCI_OBJECT, (void  *)0,
                    0, 0, 0, (size_t) 0, (void  **)0);

     /* allocate a server handle */
(void) OCIHandleAlloc ((void  *)myenvhp, (void  **)&mysrvhp,
      OCI_HTYPE_SERVER, 0, (void  **) 0);

      /* allocate an error handle */
(void) OCIHandleAlloc ((void  *)myenvhp, (void  **)&myerrhp,
      OCI_HTYPE_ERROR, 0, (void  **) 0);

      /* create a server context */
(void) OCIServerAttach (mysrvhp, myerrhp, (text *)"inst1_alias",
      strlen ("inst1_alias"), OCI_DEFAULT);

     /* allocate a service handle */
(void) OCIHandleAlloc ((void  *)myenvhp, (void  **)&mysvchp,
      OCI_HTYPE_SVCCTX, 0, (void  **) 0);

 /* set the server attribute in the service context handle*/
(void) OCIAttrSet ((void  *)mysvchp, OCI_HTYPE_SVCCTX,
       (void  *)mysrvhp, (ub4) 0, OCI_ATTR_SERVER, myerrhp);

      /* allocate a user session handle */
(void) OCIHandleAlloc ((void  *)myenvhp, (void  **)&myusrhp,
     OCI_HTYPE_SESSION, 0, (void  **) 0);

      /* set user name attribute in user session handle */
 (void) OCIAttrSet ((void  *)myusrhp, OCI_HTYPE_SESSION,
      (void  *)"hr", (ub4)strlen("hr"),
      OCI_ATTR_USERNAME, myerrhp);

      /* set password attribute in user session handle */
 (void) OCIAttrSet ((void  *)myusrhp, OCI_HTYPE_SESSION,
      (void  *)"hr", (ub4)strlen("hr"),
      OCI_ATTR_PASSWORD, myerrhp);

 (void) OCISessionBegin ((void  *) mysvchp, myerrhp, myusrhp,
      OCI_CRED_RDBMS, OCI_DEFAULT);

    /* set the user session attribute in the service context handle*/
 (void) OCIAttrSet ((void  *)mysvchp, OCI_HTYPE_SVCCTX,
       (void  *)myusrhp, (ub4) 0, OCI_ATTR_SESSION, myerrhp);
...
}

demoディレクトリ内のデモ・プログラムcdemo81.cは、このプロセスとエラー・チェックを例示しています。

OCIでのSQL文の処理

この章では、OCIでのSQL文の処理に含まれる特定のステップについて説明します。

コミットまたはロールバック

アプリケーションは、OCITransCommit()をコールすることにより、データベースへの変更をコミットします。このコールは、サービス・コンテキストをパラメータの1つとして使用します。トランザクションは、変更がコミットされるサービス・コンテキストに対応付けられています。このトランザクションは、アプリケーションで明示的に作成されたか、または、アプリケーションがデータベースを変更したときに暗黙的に作成された可能性があります。


注意:


OCIExecute()コールのOCI_COMMIT_ON_SUCCESSモードを使用すると、トランザクションをコミットするかどうかを、各文の実行後にアプリケーションで選択できるため、ラウンドトリップを削減できます。

トランザクションをロールバックするには、OCITransRollback()コールを使用します。

通常のログオフ以外のなんらかの方法でアプリケーションとOracleの接続が切断された場合(ネットワークとの接続が切れるなど)、OCITransCommit()をコールしていないと、アクティブ・トランザクションはすべて自動的にロールバックされます。

アプリケーションの終了

OCIアプリケーションは、終了する前に、次の3つのステップの実行が必要です。

  1. 各セッションに対してOCISessionEnd()をコールし、ユーザー・セッションを終了します。

  2. 各データ・ソースに対してOCIServerDetach()をコールし、データ・ソースへのアクセスを終了します。

  3. 各ハンドルに対してOCIHandleFree()をコールし、明示的に全ハンドルの割当てを解除します。

  4. 環境ハンドルを削除し、環境ハンドルに関連付けられたその他のハンドルの割当てをすべて解除します。


    注意:


    親ハンドルが解放されると、それに対応付けられた子ハンドルもすべて自動的に解放されます。

OCIServerDetach()およびOCISessionEnd()のコールは、必須ではありませんが、お薦めします。アプリケーションがOCITransCommit()(トランザクション・コミット)をコールしないで終了すると、保留状態のトランザクションはすべて自動的にロールバックされます。


関連項目:


ハンドルがアプリケーションの終了時に解放される様子を示した例は、付録B「OCIデモ・プログラム」の最初のサンプル・プログラムを参照してください。


注意:


アプリケーションでOCILogon()の単純化されたログイン方法を使用する場合は、OCILogoff()をコールするとセッションが終了し、サーバーとの接続が切断され、サービス・コンテキスト・ハンドルとそれに関連付けられたハンドルが解放されます。ただし、アプリケーションにより割り当てた他のハンドルは、そのアプリケーションから解放してください。

OCIでのエラー処理

OCIファンクション・コールには、表2-3「OCIリターン・コード」にリストされた一連のリターン・コードが用意されています。これらのコードにより、コールの成功または失敗(OCI_SUCCESSOCI_ERRORなど)や、アプリケーションが必要とするその他の情報(OCI_NEED_DATAOCI_STILL_EXECUTINGなど)が示されます。大部分のOCIコールは、これらのコードの1つを戻します。

サーバーへの接続がOCI_ERRORで終了しないように、アプリケーションでは、サーバー・ハンドル内の属性OCI_ATTR_SERVER_STATUSの値をチェックできます。属性の値がOCI_SERVER_NOT_CONNECTEDの場合、サーバーへの接続およびユーザー・セッションを再確立する必要があります。


関連項目:


表2-3 OCIリターン・コード

OCIリターン・コード 説明

OCI_SUCCESS

関数は正常に終了しました。

OCI_SUCCESS_WITH_INFO

関数は正常に終了しました。OCIErrorGet()をコールすると、追加診断情報が戻されます。これには、警告が含まれる場合があります。

OCI_NO_DATA

関数が終了しました。これ以上データはありません。

OCI_ERROR

関数が失敗しました。OCIErrorGet()をコールすると、エラーの追加情報が戻されます。

OCI_INVALID_HANDLE

無効なハンドルがパラメータとして渡されたか、ユーザー・コールバックで無効なハンドルまたは無効なコンテキストが渡されました。追加診断情報はありません。

OCI_NEED_DATA

アプリケーションで、ランタイム・データを提供する必要があります。

OCI_STILL_EXECUTING

サービス・コンテキストが非ブロック化モードで確立されたため、現行の操作は即時完了できませんでした。この操作を完了するには、これを再度コールする必要があります。OCIErrorGet()がエラー・コードとしてORA-03123を戻します。

OCI_CONTINUE

このコードはコールバック関数からのみ戻されます。これは、コールバック関数が、OCIライブラリの標準処理再開を示唆していることを示します。


エラーが発生したことがリターン・コードに示されている場合、アプリケーションではOCIErrorGet()をコールして、Oracle固有のエラー・コードおよびメッセージを取り出せます。OCIErrorGet()へのパラメータの1つは、エラーが発生したコールに渡されたエラー・ハンドルです。


注意:


レコードがなくなる(OCI_NO_DATAが戻される)まで、繰り返しOCIErrorGet()をコールすると、複数の診断レコードを取り出すことができます。OCIErrorGet()は、最大1個の診断レコードを戻します。

データのリターン・コードおよびエラー・コード

表2-4に、フェッチされたデータが正常、NULL、または切捨ての場合の、OCIリターン・コード、エラー番号、標識変数および列リターン・コードを示します。


関連項目:


標識変数の詳細は、「標識変数」を参照してください。

表2-4 リターン・コードとエラー・コード

データの状態 リターン・コード インジケータ − 戻さない場合 インジケータ − 戻す場合

NULL、切捨て以外

戻さない場合

OCI_SUCCESS

error = 0

OCI_SUCCESS

error = 0

indicator = 0

NULL、切捨て以外

戻す場合

OCI_SUCCESS

error = 0

return code = 0

OCI_SUCCESS

error = 0

indicator = 0

return code = 0

NULLデータ

戻さない場合

OCI_ERROR

error = 1405

OCI_SUCCESS

error = 0

indicator = -1

NULLデータ

戻す場合

OCI_ERROR

error = 1405

return code = 1405

OCI_SUCCESS

error = 0

indicator = -1

return code = 1405

切捨てデータ

戻さない場合

OCI_ERROR

error = 1406

OCI_ERROR

error = 1406

indicator = data_len

切捨てデータ

戻す場合

OCI_SUCCESS_WITH_INFO

error = 24345

return code = 1405

OCI_SUCCESS_WITH_INFO

error = 24345

indicator = data_len

return code = 1406


切捨てデータの場合、data_lenは、長さがSB2MAXVAL以下であった場合に切り捨てられたデータの実際の長さです。この値を超えていれば、インジケータが-2に設定されます。

その他の値を戻す関数

一部の関数では、表2-3にリストされているOCIエラー・コード以外の値を戻します。これらの関数を使用する場合、OUTパラメータからではなく、ファンクション・コールから直接値が戻ります。それぞれの関数と戻り値の詳細は、該当する章を参照してください。

その他のコーディング・ガイドライン

この項では、OCIアプリケーションをコーディングするときのその他の問題について説明します。

パラメータの型

OCI関数には整数、ハンドル、文字列など、多様なデータ型のパラメータを使用することができます。パラメータの型によっては注意事項があり、以降の項で説明します。


関連項目:


パラメータのデータ型、およびパラメータを渡す際の規則の詳細は、「接続関数、認証関数および初期化関数」を参照してください。

アドレス・パラメータ

アドレス・パラメータは、変数のアドレスをOracleに渡すために使用されます。Cでは、通常スカラー・パラメータを値で渡すので、Cで開発する場合は注意してください。

整数パラメータ

2進整数およびshort型2進整数パラメータは、サイズがシステムによって異なる数値です。使用しているシステムでのこれらの整数のサイズについては、システム固有のOracleマニュアルを参照してください。

文字列パラメータ

文字列は、アドレス・パラメータの特殊な型です。文字列をパラメータとして渡すことができる各OCIルーチンには、文字列長のパラメータもあります。このパラメータで文字列の長さを設定する必要があります。


7.xアップグレードの注意:


OCIのこれまでのバージョンとは異なり、ヌル文字で終了する文字列の文字列長パラメータに-1を渡すことはできません。

列へのNULLの挿入

データベース列にNULLを挿入する方法はいくつかあります。

  1. 1つは、INSERT文またはUPDATE文のテキストの中でリテラルNULLを使用する方法です。たとえば、次のようなSQL文があるとします。

     INSERT INTO emp1 (ename, empno, deptno)
        VALUES (NULL, 8010, 20)

この文では、ENAME列がNULLになります。

  1. OCIバインド・コールでは、標識変数を使用します。


    関連項目:


    「標識変数」

  2. NULLを挿入するには、バッファ長パラメータと最大長パラメータの両方を、バインド・コールで0(ゼロ)に設定します。


    注意:


    対応する標識変数が定義コールで指定されていても、その標識変数を含まない変数にNULL選択リスト項目をフェッチすると、OracleはSQL92要件に従いエラーを戻します。

標識変数

各バインドと定義OCIコールには、標識変数または標識変数の配列をDML文、PL/SQL文または問合せに関連付けるパラメータがあります。

C言語にはNULL値の概念がありません。したがって、標識変数と入力変数を関連付けることによって、関連付けられたプレースホルダがNULLであるかどうかを指定します。データがOracleに渡されるとき、これらの標識変数の値によって、NULLがデータベース・フィールドに割り当てられているかどうかが判断されます。

出力変数では、標識変数によって、Oracleから戻された値がNULLまたは切り捨てられた値であるかどうかが判断されます。OCIStmtFetch()コールでのNULLフェッチ、またはOCIStmtExecute()コールでの切捨ての場合は、OCIコールによりOCI_SUCCESS_WITH_INFOが戻されます。出力標識変数が設定されます。

標識変数のデータ型はsb2です。標識変数の配列の場合、各配列要素の型はsb2です。

入力

入力ホスト変数については、OCIアプリケーションは次の値を標識変数に割り当てることができます。

入力インジケータ値 Oracleからのアクション
-1 OracleはNULLを列に割り当て、入力変数の値は無視します。
>=0 入力変数の値を列に割り当てます。

出力

出力については、Oracleは次の値を標識変数に割り当てます。

出力インジケータ値 意味
-2 項目の長さが出力変数の長さよりも長いため、項目を切り捨てます。さらに、元の長さが、sb2標識変数で戻せる最大長より長くなっています。
-1 選択された値がNULLで、出力変数の値は変更されません。
0 完全な値をホスト変数に割り当てます。
>0 項目の長さが出力変数の長さよりも長いため、項目を切り捨てます。標識変数に戻された正の値は、切捨て前の実際の長さです。

名前付きデータ型用およびREF用の標識変数

リリース8.0より後に導入されたデータ型の標識変数は、前述の説明どおりに機能します。例外はSQLT_NTY(名前付きデータ型)です。SQLT_NTY型のデータの場合、標識変数はインジケータ構造体へのポインタである必要があります。SQLT_REF型のデータでは、他の変数型と同様に、標準のスカラー・インジケータを使用します。

Object Type Translator(OTT)を使用してデータベース型をC構造体に変換すると、各オブジェクト型についてNULLインジケータ構造体が生成されます。この構造体には、アトミックNULLインジケータと各オブジェクト属性のインジケータが含まれます。


関連項目:


コールの取消し

ほとんどのオペレーティング・システムでは、キーボードからオペレーティング・システムの割込み文字(通常は[Ctrl] + [C]キー)を入力することで、長時間実行されたり繰り返されているOCIコールを取り消すことができます。


注意:


OCIコールの取消しをカーソルの取消しと混同しないように注意してください。カーソルの取消しは、nrowsパラメータを0(ゼロ)に設定し、OCIStmtFetch()をコールして行います。

長時間実行されたり繰り返されているコールをオペレーティング・システムへの割込みにより取り消した場合は、エラー・コードORA-01013「ユーザーによって現行の操作の取消しが要求されました。」が戻されます。

特定のサービス・コンテキスト・ポインタまたはサーバー・コンテキスト・ポインタを指定すると、OCIBreak()関数は、サーバーに関連付けられている現在実行中のOCI関数をすべて即時(非同期)に停止します。これは通常、サーバーで長時間実行されている処理中のOCIコールを停止するために使用します。OCIReset()関数は、OCIアプリケーションがOCIBreak()で機能を停止した後で、非ブロック化接続に対してプロトコル同期化を実行するために必要です。


注意:


OCIBreak()は、Windows 2000やWindows XPなどのWindowsシステムで作動します。

長時間実行する可能性のあるコールは、非ブロック化コールを使用することによりステータスを監視することができます。新しいアプリケーションでは、マルチスレッドを使用します。

位置指定の更新および削除

SELECT...FOR UPDATE OF...文に関連付けられたROWIDを、後のUPDATE文またはDELETE文に使用できます。ROWIDは、文ハンドルに対してOCIAttrGet()をコールして取り出すことができ、これによりこのハンドルのOCI_ATTR_ROWID属性を取り出せます。

たとえば、次のようなSQL文があるとします。

SELECT ename FROM emp1 WHERE empno = 7499 FOR UPDATE OF sal

この場合、フェッチが実行されると、ハンドルのROWID属性には選択された行の行識別子が入ります。次のコードのようにOCIAttrGet()をコールして、プログラムのバッファにROWIDを取り出すことができます。

OCIRowid *rowid;   /* the rowid in opaque format */
/* allocate descriptor with OCIDescriptorAlloc() */
status = OCIDescriptorAlloc ((void  *) envhp, (void  **) &rowid,
     (ub4) OCI_DTYPE_ROWID, (size_t) 0, (void  **) 0);
status = OCIAttrGet ((void *) mystmtp, OCI_HTYPE_STMT,
     (void *) rowid, (ub4 *) 0, OCI_ATTR_ROWID, (OCIError *) myerrhp);

その後、保存されたROWIDDELETE文またはUPDATE文で使用できます。たとえば、rowidが行識別子の保存されているバッファである場合、後で次のようなSQL文を処理できます。

UPDATE emp1 SET sal = :1 WHERE rowid = :2

これは、新しいsalary(給与)をプレースホルダ:1にバインドし、rowidをプレースホルダ:2にバインドして行います。rowid:2にバインドする場合は、必ずデータ型コード104(ROWID記述子)を使用してください。

プリフェッチを使用して、ROWIDの配列を後続のバッチ更新で使用するために選択できます。


関連項目:


ROWIDの詳細は、「UROWID」および「DATE」を参照してください。

予約語

一部のワードはOracleによって確保されています。つまり、それらのワードはOracleにとって特別な意味を持っており、再定義できません。このため、それらのワードを使用して、列、表、索引などのデータベース・オブジェクトに名前を付けることはできません。


関連項目:


SQLおよびPL/SQL用のOracleのキーワードまたは予約語のリストについては、『Oracle Database SQLリファレンス』および『Oracle Database PL/SQL言語リファレンス』を参照してください。

Oracle予約済ネームスペース

表2-5「Oracle予約済ネームスペース」は、Oracleによって予約されているネームスペースのリストです。Oracleライブラリ内の関数名の最初の文字列は、このリストの文字列に制限されています。名前が競合する可能性があるため、これらの文字列で始まる関数名を付けないでください。

表2-5 Oracle予約済ネームスペース

ネームスペース ライブラリ

XA

XAアプリケーション専用の外部関数

SQ

OracleのプリコンパイラおよびSQL*Moduleアプリケーションで使用される外部SQLLIB関数

O、OCI

外部OCI関数、内部OCI関数

UPI、KP

Oracle UPIレイヤーの関数名

NA

NC

ND

NL

NM

NR

NS

NT

NZ

OS

TTC

Oracle Netネイティブ・サービス・プロダクト

Oracle Net Rpcプロジェクト

Oracle Netディレクトリ

Oracle Netネットワーク・ライブラリ・レイヤー

Oracle Net管理プロジェクト

Oracle Netインターチェンジ

Oracle Netトランスペアレント・ネットワーク・サービス

Oracle Netドライバ

Oracle Netセキュリティ・サービス

SQL*Netバージョン1

Oracle Net 2タスク

GEN、L、ORA

コア・ライブラリ関数

LI、LM、LX

Oracleグローバリゼーション・サポート・レイヤーの関数名

S

システム依存ライブラリの関数名

KO

カーネル・オブジェクト


特定のネームスペースのすべての関数リストは、該当するOracleライブラリに対応したドキュメントを参照してください。

OCIでの非ブロック化モード

非ブロック化モードではラウンドトリップ回数とCPU使用率が増加するため、新しいアプリケーションではマルチスレッド・コールを使用します。

OCIでは、ブロック化モードまたは非ブロック化モードでサーバー接続を確立できます。接続がブロック化モードで行われた場合、結果が正常かエラーかにかかわらずコールが完了した場合にのみ、OCIコールはコントロールをOCIクライアント・アプリケーションに戻します。非ブロック化モードでは、コールが完了せずコールからOCI_STILL_EXECUTINGの値が戻されても、コントロールはただちにOCIプログラムに戻されます。

非ブロック化モードでは、アプリケーションで各OCI関数のリターン・コードをテストし、OCI_STILL_EXECUTINGが戻されるかどうかを確認する必要があります。この場合、OCIクライアントはこのOCIコールのサーバーでの再試行を待つ間、プログラム・ロジックの処理を継続できます。このモードは、Graphical User Interface(GUI)アプリケーション、リアルタイム・アプリケーションおよび分散環境の場合に特に有用です。

非ブロック化モードは非割込み駆動で、むしろポーリング・パラダイムに基づいています。これは、保留状態のコールがサーバーで終了したかどうかを、同一パラメータでそのコールを再び実行することにより、クライアント・アプリケーションがチェックする必要があることを意味します。

次の機能および関数は、非ブロック化モードではサポートされません。

  • ダイレクト・パス・ローダー

  • LOBバッファリング

  • オブジェクト

  • 問合せキャッシュ

  • スクロール・カーソル

  • TAF

  • OCIAQEnqArray()

  • OCIAQDeqArray()

  • OCIDescribeAny()

  • OCILobArrayRead()

  • OCILobArrayWrite()

  • OCITransStart()

  • OCITransDetach()


注意:


非ブロック化OCIコールの再試行を待機している間、アプリケーションでは、待機している非ブロック化OCIに関連する他のOCIコールを実行しないでください。他のコールを実行すると、ORA-03124またはORA-24386のエラーが発生したり、場合によってはアプリケーションが停止することがあります。 このルールの唯一の例外は、OCIBreak()コールとOCIReset()コールです。

ブロック化モードの設定

アプリケーションのブロック化状態は、attrtypeパラメータをOCI_ATTR_NONBLOCKING_MODEに設定して、サーバー・コンテキスト・ハンドルでOCIAttrSet()をコールして状態を設定したり、OCIAttrGet()をコールして状態を読み取ることにより、変更またはチェックすることができます。この属性を設定できるのは、OCISessionBegin()またはOCILogon2()がコールされた後でのみです。設定されていない場合は、エラーが戻されます。


注意:


パラメータとしてサーバー・コンテキスト・ハンドルまたはサービス・コンテキスト・ハンドルを持つ関数のみが、OCI_STILL_EXECUTINGを戻します。

非ブロック化コールの取消し

OCIコールの実行中にOCIBreak()関数を使用することにより、長時間実行しているOCIコールを取り消すことができます。その後、OCIReset()コールを発行して、非同期操作およびプロトコルをリセットする必要があります。

OCIプログラムでのPL/SQL使用方法

PL/SQLは、Oracleが開発したSQL言語の手続き型拡張機能です。PL/SQLは、単純な問合せやSQLデータ操作言語(DML)文よりも複雑なタスクをサポートします。PL/SQLを使用すると、複数の構文を単一のブロックにグループ化し、それを1単位として実行できます。次のような構文があります。

OCIプログラムでPL/SQLブロックを使用して、次の操作ができます。

OCIグローバリゼーション・サポート

次の項では、ロケール情報の導出、文字列の操作、キャラクタ・セット変換、OCIメッセージなど、グローバリゼーションに使用されるOCI関数について説明します。これらの関数には複数の目的および機能があるため、詳細は、このマニュアルの他の章を参照してください。

OCIからのクライアント・キャラクタ・セットの制御

OCIEnvNlsCreate()関数は、NLS_LANGおよびNLS_NCHARの設定とは関係なく、アプリケーションでキャラクタ・セット情報を設定できます。様々なクライアント側キャラクタ・セットIDおよび各国語キャラクタ・セットIDを使用して、同じシステム環境内で初期化した複数の環境ハンドルを1つのアプリケーションで使用できます。

OCIEnvNlsCreate(OCIEnv **envhp, ..., csid, ncsid);

csidはキャラクタ・セットIDの値で、ncsidは各国語キャラクタ・セットIDの値です。いずれの値も0(ゼロ)またはOCI_UTF16IDに設定できます。両方とも0(ゼロ)の場合は、OCIEnvCreate()を使用するのと同じになります。その他の引数は、OCIEnvCreate()コールの引数と同じです。

OCIEnvNlsCreate()は、OCI_UTF16IDを検証するため、キャラクタ・セットをプログラムによって制御するための拡張機能です。

OCIEnvNlsCreate()関数を使用してキャラクタ・セットIDを設定すると、NLS_LANGおよびNLS_NCHARの設定値が置換されます。OCIEnvNlsCreate()関数では、NLSRTLでサポートされるすべてのキャラクタ・セット以外に、OCI_UTF16IDをキャラクタ・セットIDとして設定できます(NLS_LANGまたはNLS_NCHARでは無効となります)。

AL16UTF16を除くすべてのOracleキャラクタ・セットIDは、OCIEnvNlsCreate()関数を使用して指定され、メタデータのエンコーディング、SQL CHARデータおよびSQL NCHARデータを指定できます。

NLS_LANGおよびNLS_NCHARのキャラクタ・セットは、関数のOCINlsEnvironmentVariableGet()を使用して取得できます。

OCIでキャラクタ・セットを制御するコードの例

擬似コード・フラグメントは、前述のコールの使用例を示します。

文字制御とOCIインタフェース

OCINlsGetInfo()は、OCI_UTF16IDがOCIEnvNlsCreate()で使用されている場合に、OCI_UTF16IDに関する情報を戻します。

OCIAttrGet()は、OCIEnvNlsCreate()に渡されたキャラクタ・セットIDおよび各国語キャラクタ・セットIDを戻します。これは、OCI_ATTR_ENV_CHARSET_IDおよびOCI_ATTR_ENV_NCHARSET_IDを取得するために使用されます。これには、値OCI_UTF16IDが含まれます。

OCIEnvNlsCreate()を使用してcharsetおよびncharsetパラメータにNULLが設定されている場合は、NLS_LANGおよびNLS_NCHARのキャラクタ・セットIDが戻されます。

この関数を使用してOCI_ATTR_CHARSET_FORMがリセットされている場合、OCIAttrSet()は文字IDをデフォルトとして設定します。OCI_UTF16IDは、OCIEnvNlsCreate()charsetまたはncharsetとして渡される場合、有効なキャラクタ・セットIDの1つになります。

OCIBindByName()およびOCIBindByPos()は、OCIEnvNlsCreate()コールのデフォルトのキャラクタ・セット(OCI_UTF16IDを含む)を使用して、変数をバインドします。OCIEnvNlsCreate()を使用する場合、実際の長さと戻される長さは常にバイト単位で表されます。

OCIDefineByPos()は、OCIEnvNlsCreate()charsetの値(OCI_UTF16IDを含む)を持つ変数をデフォルトとして定義します。OCIEnvNlsCreate()を使用する場合、実際の長さと戻される長さは常にバイト単位で表されます。バインド・ハンドルおよび定義ハンドルのこの動作は、OCIEnvCreate()を使用する場合とは異なり、OCI_UTF16IDはバインド・ハンドルおよび定義ハンドル用のキャラクタ・セットIDになります。

OCIでの文字長セマンティクス

OCIは、サーバーとクライアント間のトランスレータとして機能し、制約チェックを行うための文字情報を渡します。

キャラクタ・セットには可変幅と固定幅の2種類があります。シングルバイト・キャラクタ・セットは、各バイトが1つの文字を表す固定幅キャラクタ・セットの特殊なケースです。

固定幅キャラクタ・セットの場合、バイト数は文字数の倍数であるため、制約チェックが簡単です。したがって、固定幅キャラクタ・セットでは、文字数を調べるために文字列全体をスキャンする必要がありません。これに対して、可変幅キャラクタ・セットでは、文字列全体をスキャンして文字数を調べる必要があります。

OCIでのキャラクタ・セットのサポート

詳細は、「記述での文字長セマンティクスのサポート」および「OCIバインドおよび定義における文字変換」を参照してください。

その他のOCIグローバリゼーション・サポート関数

グローバリゼーション・サポート関数は、環境ハンドルまたはユーザー・セッション・ハンドルを受け入れます。OCI環境ハンドルは、クライアントのNLS環境変数に関連付けられます。ALTER SESSION文がサーバーに発行された場合、この環境は変更されません。環境ハンドルに関連付けられたキャラクタ・セットは、クライアント・キャラクタ・セットです。OCIセッションハンドル(OCISessionBegin()によって戻されます)は、サーバー・セッション環境に関連付けられます。ALTER SESSION文でセッション環境が変更された場合、NLS設定も変更されます。セッション・ハンドルに関連付けられたキャラクタ・セットは、データベース・キャラクタ・セットです。

セッションで最初のトランザクションが開始されるまで、OCIセッション・ハンドルには、関連付けられたNLS設定がないことに注意してください。SELECT文では、トランザクションは開始されません。

関数の詳細および説明は、次を参照してください。


関連項目:


OCIでのロケール情報の取得

Oracleロケールは、言語、地域およびキャラクタ・セット定義で構成されます。ロケールは、曜日と月の名前、および日付、時刻、数値、通貨の書式などの表記規則を決定します。グローバル化されたアプリケーションは、ユーザーのロケール設定および文化の規則に対応しています。たとえば、ロケールをドイツに設定すると、月日の名前がドイツ語で表示されます。

OCINlsGetInfo()関数を使用して、次の情報を取得できます。

  • 曜日(翻訳済)

  • 曜日の略称(翻訳済)

  • 月名(翻訳済)

  • 月名の略称(翻訳済)

  • はい/いいえ(翻訳済)

  • AM/PM(翻訳済)

  • AD/BC(翻訳済)

  • 数値書式

  • 借方/貸方

  • 日付書式

  • 通貨書式

  • デフォルトの言語

  • デフォルトの地域

  • デフォルト・キャラクタ・セット

  • デフォルトの言語ソート

  • デフォルト・カレンダ

OCIでのロケール情報取得の例

次のサンプル・コードは、ロケール情報を取得して、エラーをチェックします。

sword MyPrintLinguisticName(envhp, errhp)
OCIEnv   *envhp;
OCIError *errhp;
{
  OraText  infoBuf[OCI_NLS_MAXBUFSZ];
  sword ret;

  ret = OCINlsGetInfo(envhp,                           /* environment handle */
                      errhp,                                 /* error handle */
                      infoBuf,                         /* destination buffer */
                      (size_t) OCI_NLS_MAXBUFSZ,              /* buffer size */
                      (ub2) OCI_NLS_LINGUISTIC_NAME);                /* item */

  if (ret != OCI_SUCCESS)
  {
    checkerr(errhp, ret, OCI_HTYPE_ERROR);
    ret = OCI_ERROR;
  }
  else
  {
    printf("NLS linguistic: %s\n", infoBuf);
   }
  return(ret);
}

OCIでの文字列の操作

文字列操作では、マルチバイト文字列およびワイド・キャラクタ文字列がサポートされています。

マルチバイト文字列は、システム固有のOracleキャラクタ・セットでエンコードされています。マルチバイト文字列で動作する関数は、バイト単位で計算された文字列の長さを使用して、文字列全体を1つの単位として使用します。ワイド・キャラクタ文字列(wchar)関数を使用すると、より柔軟に文字列を操作できます。ワイド・キャラクタ文字列は、文字ベースおよび文字列ベースの操作をサポートします。この場合、文字列の長さは、文字単位で計算されます。

ワイドキャラクタ・データ型OCIWcharはOracle固有のものです。ANSI/ISO C標準で定義されているwchar_tデータ型と混同しないでください。Oracleワイド・キャラクタ・データ型は、すべてのオペレーティング・システムで常に4バイトですが、wchar_tのサイズは、実装およびオペレーティング・システムによって異なります。Oracleワイド・キャラクタ・データ型は、マルチバイト文字を正規化するため、統一された固定幅になり、処理が簡単になります。これにより、Oracleワイド・キャラクタ・セットとシステム固有のキャラクタ・セット間でラウンドトリップ変換を行った場合でも、データは失われません。

文字列操作は、次のカテゴリに分類できます。

  • マルチバイト・キャラクタとワイド・キャラクタ間の文字列変換

  • 文字の分類

  • 大/小文字の変換

  • 表示長の計算

  • 比較、連結、検索などの一般的な文字列操作

OCIでの文字列操作の例

単純な文字列操作の例を次に示します。

size_t MyConvertMultiByteToWideChar(envhp, dstBuf, dstSize, srcStr)
OCIEnv     *envhp;
OCIWchar   *dstBuf;
size_t      dstSize;
OraText    *srcStr;                         /* null terminated source string */
{
  sword  ret;
  size_t dstLen = 0;
  size_t srcLen;

  /* get length of source string */
  srcLen = OCIMultiByteStrlen(envhp, srcStr);

  ret = OCIMultiByteInSizeToWideChar(envhp,            /* environment handle */
                 dstBuf,                               /* destination buffer */
                 dstSize,                         /* destination buffer size */
                 srcStr,                                    /* source string */
                 srcLen,                          /* length of source string */
                 &dstLen);                  /* pointer to destination length */

  if (ret != OCI_SUCCESS)
  {
    checkerr(envhp, ret, OCI_HTYPE_ENV);
  }
  return(dstLen);
}

OCIでの文字列分類の例

OCIの文字列分類機能について、詳しく説明します。

OCIで文字列を分類する方法の例を次に示します。

boolean MyIsNumberWideCharString(envhp, srcStr)
OCIEnv   *envhp;
OCIWchar *srcStr;                                 /* wide char source string */
{
  OCIWchar *pstr = srcStr;                        /* define and init pointer */
  boolean status = TRUE;            /* define and initialize status variable */

  /* Check input */
  if (pstr == (OCIWchar*) NULL)
    return(FALSE);


  if (*pstr == (OCIWchar) NULL)
    return(FALSE);

                                            /* check each character for digit */
  do
  {
    if (OCIWideCharIsDigit(envhp, *pstr) != TRUE)
    {
      status = FALSE;
      break;                                  /* non-decimal digit character */
    }
  } while ( *++pstr != (OCIWchar) NULL);

  return(status);
}

OCIでのキャラクタ・セットの変換

Oracleキャラクタ・セットとUnicode(16ビット、固定幅のUnicodeエンコーディング)間の変換がサポートされています。UnicodeからOracleキャラクタ・セットへの文字のマッピングが存在しない場合、置換文字が使用されます。したがって、変換して元のキャラクタ・セットに戻す場合、データが失われる可能性があります。

Unicodeキャラクタ・セットに関連するキャラクタ・セット変換関数では、データのバインド・バッファおよび定義バッファをub2アドレスで揃える必要があります。揃っていない場合、エラーが発生します。

OCIでのキャラクタ・セット変換の例

Unicodeへの単純な変換の例を次に示します。

/* Example of Converting Character Sets in OCI
--------------------------------------------*/

size_t MyConvertMultiByteToUnicode(envhp, errhp, dstBuf, dstSize, srcStr)
OCIEnv   *envhp;
OCIError *errhp;
ub2 *dstBuf;
size_t dstSize;
OraText *srcStr;
{
  size_t dstLen = 0;
  size_t srcLen = 0;
  OraText tb[OCI_NLS_MAXBUFSZ];   /* NLS info buffer */
  ub2    cid;                     /* OCIEnv character set id */

  /* get OCIEnv character set */
  checkerr(errhp, OCINlsGetInfo(envhp, errhp, tb, sizeof(tb),
                                OCI_NLS_CHARACTER_SET));
  cid = OCINlsCharSetNameToId(envhp, tb);

  if (cid == OCI_UTF16ID)
  {
    ub2    *srcStrUb2 = (ub2*)srcStr;
    while (*srcStrUb2++) ++srcLen;
    srcLen *= sizeof(ub2);
  }
  else
    srcLen = OCIMultiByteStrlen(envhp, srcStr);

  checkerr(errhp,
    OCINlsCharSetConvert(
      envhp,       /* environment handle */
      errhp,       /* error handle */
      OCI_UTF16ID, /* Unicode character set id */
      dstBuf,      /* destination buffer */
      dstSize,     /* size of destination buffer */
      cid,         /* OCIEnv character set id */
      srcStr,      /* source string */
      srcLen,      /* length of source string */
      &dstLen));   /* pointer to destination length */

  return dstLen/sizeof(ub2);
}

OCIメッセージ関数

ユーザー・メッセージAPIは、カートリッジ開発者が、独自のメッセージおよびOracleメッセージを取得するための単純なインタフェースを提供します。


関連項目:


テキスト・メッセージ・ファイルからのメッセージ取得の例

次の例では、メッセージ・ハンドルを作成し、impus.msgからメッセージを取得するために初期化して、メッセージ番号128を取得し、メッセージ・ハンドルをクローズします。この例では、OCI環境ハンドル、OCIセッション・ハンドル、製品、機能およびキャッシュ・サイズが正しく初期化されていることを想定しています。

OCIMsg msghnd;                                              /* message handle */
         /* initialize a message handle for retrieving messages from impus.msg*/
err = OCIMessageOpen(hndl,errhp, &msghnd, prod,fac,OCI_DURATION_SESSION);
if (err != OCI_SUCCESS)
                                                            /* error handling */
...
                            /* retrieve the message with message number = 128 */
msgptr = OCIMessageGet(msghnd, 128, msgbuf, sizeof(msgbuf));
                         /* do something with the message, such as display it */
...
      /* close the message handle when there are no more messages to retrieve */
OCIMessageClose(hndl, errhp, msghnd);

lmsgenユーティリティ

lmsgenユーティリティは、テキストベースのメッセージ・ファイル(.msg)をバイナリ形式(.msb)に変換します。これにより、ユーザーが提供したOracleメッセージおよびOCIメッセージを、希望する言語でOCI関数に戻すことができます。

lmsgenのBNF構文

lmsgen text_file product facility [language]

次のように指定します。

  • text_fileは、メッセージ・テキスト・ファイルです。

  • productは、製品の名前です。

  • facilityは、機能の名前です。

  • languageは、NLS_LANGパラメータで指定された言語に対応する、オプションのメッセージ言語です。メッセージ・ファイルに言語のタグが正しく付いていない場合は、言語パラメータが必要です。

テキスト・メッセージ・ファイルのガイドライン

  • "/"および"//"で始まる行は、内部コメントとみなされるため、無視されます。

  • メッセージ・ファイルに特定の言語のタグを付けるには、次のような行を含めます。

    #   CHARACTER_SET_NAME= Japanese_Japan.JA16EUC
    
  • 各メッセージには、3つのフィールドがあります。

    message_number, warning_level, message_text
    
  • メッセージ番号は、メッセージ・ファイル内で一意であることが必要です。

  • 警告レベルは、現在使用されていません。0に設定します。

  • メッセージ・テキストは、76バイトより長くできません。

Oracleメッセージ・テキスト・ファイルの例を次に示します。

/ Copyright (c) 2001 by the Oracle Corporation.  All rights reserved.
/ This is a test us7ascii message file
# CHARACTER_SET_NAME= american_america.us7ascii
/
00000, 00000, "Export terminated unsuccessfully\n"
00003, 00000, "no storage definition found for segment(%lu, %lu)"

例: テキスト・メッセージ・ファイルからのバイナリ・メッセージ・ファイルの作成

次の表は、lmsgenパラメータのサンプル値を示します。

lmsgenパラメータ
product $HOME/myApplication
facility imp
language AMERICAN
text_file impus.msg

テキスト・メッセージ・ファイルの場所は、次のとおりです。

$HOME/myApp/mesg/impus.msg

テキスト・メッセージ・ファイル内の1行は、次のとおりです。

00128,2, "Duplicate entry %s found in %s"

lmsgenユーティリティは、テキスト・メッセージ・ファイル(impus.msg)をバイナリ形式に変換します。これにより、impus.msbというファイルが作成されます。

% lmsgen impus.msg $HOME/myApplication imp AMERICAN

出力結果は、次のようになります。

Generating message file impus.msg -->
/home/scott/myApplication/mesg/impus.msb

NLS Binary Message File Generation Utility: Version 9.2.0.0.0 -Production

Copyright (c) Oracle Corporation 1979, 2001.  All rights reserved.

CORE    9.2.0.0.0       Production