プライマリ・コンテンツに移動
Oracle® Call Interfaceプログラマーズ・ガイド
12c リリース1 (12.1)
B72465-07
目次へ移動
目次
索引へ移動
索引

前
次

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

この章では、OCIを使用してプログラムを作成する際に必要となる概念および手順について説明します。

この章を読み終えると、基本的なOCIアプリケーションの作成に必要なツールについてほとんど習得したことになります。

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

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

関連項目:

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

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

ヘッダー・ファイルおよびMakefileの場所

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

これらのファイルは、Oracle Databaseサーバー環境でも、Oracle Databaseクライアント管理およびカスタム環境でも使用できます。

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

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

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

ociucb.mkファイルは、demoにあるコールバック共有ライブラリ作成用Makefileです。

OCIプログラムのプログラミングの概要

OCIアプリケーションの全般的な目標は、マルチ・ユーザーのために稼働することです。

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

OCIでは、次の基本的なプログラム・フローを使用しています。

  1. OCIプログラミング環境およびスレッドの初期化により環境を作成します。

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

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

  4. プリペアド文の実行、または新規に実行する文の準備

  5. ユーザー・セッションを終了し、サーバー接続から切断します。

  6. ハンドルおよびデータ構造を解放します。

図2-1は、OCIアプリケーションのステップの流れを示しています。「OCIプログラミング・ステップ」では、各ステップをより詳細に説明しています。

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

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

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

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

注意:

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

関連項目:

オブジェクトへのアクセスおよび操作の詳細は、「OCIオブジェクト・リレーショナル・プログラミング」から「OCIでのObject Type Translatorの使用」を参照してください

OCIデータ構造

ハンドル記述子は、OCIアプリケーションで定義された不透明なデータ構造体です。

ハンドルと記述子は、特定の割当てコールによって直接割り当てるか、あるいはOCI関数を使用して暗黙的に割り当てることができます。

注意:

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

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

エラー・ハンドル

エラー・ハンドルは、大部分のOCIコールにパラメータとして渡されます。

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

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

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

サービス・コンテキスト・ハンドル は、サーバーに対するOCIコールの操作コンテキストを決定する属性を定義します。

サービス・コンテキスト・ハンドルには、サーバー接続、ユーザー・セッションおよびトランザクションを表す属性として3つのハンドルが含まれています。これらの属性は、図2-2で説明されています。

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

図2-2の説明は次にあります
「図2-2 サービス・コンテキストのコンポーネント」の説明
  • サーバー・ハンドルは、データベースへの接続を識別します。これは、接続指向のトランスポート・メカニズムによって物理接続に変換されます。

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

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

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

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

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

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

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

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

文ハンドルは、SQL文またはPL/SQL文と、それぞれに関連付けられた属性を識別するコンテキストです

図2-3に文ハンドルを示します。

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

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

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

記述ハンドル

記述ハンドルは、OCI記述コールであるOCIDescribeAny()によって使用されます。

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

関連項目:

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

複合オブジェクト検索(COR)ハンドルは、Oracle Database内のオブジェクトを操作する一部のOCIアプリケーションによって使用されます。

複合オブジェクト検索ハンドルにはCOR記述子が含まれており、これは別のオブジェクトによって参照されるオブジェクトを取得する手順を提供します。

スレッド・ハンドル

スレッド・ハンドルはマルチスレッド・アプリケーションで使用されます。

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

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

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

サブスクリプション・ハンドルは、クライアントからの登録に関するすべての情報をカプセル化します。

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

ダイレクト・パス・ハンドルは、Oracle Database内でダイレクト・パス・ロード・エンジンを利用するOCIアプリケーションに必要です。

ダイレクト・パス・ロード・インタフェースを使用して、アプリケーションからOracle Databaseのダイレクト・ブロック・フォーマッタにアクセスできます。図2-4では、各種ダイレクト・パス・ハンドルを示しています。

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

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

接続プール・ハンドル

接続プール・ハンドルは、物理接続を仮想接続にプールするアプリケーションで使用されます。

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

ハンドル属性

すべてのOCIハンドルには、そのハンドルに格納されているデータを表す属性があります。

ハンドル属性は、属性取得コールOCIAttrGet()を使用して読み取ることができ、属性設定コールOCIAttrSet()を使用して変更することもできます。

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

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

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

関連項目:

例2-1 セッション・ハンドルでユーザー名を設定するためのOCI_ATTR_USERNAME属性の使用

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

例2-2 選択リスト項目に関する記述情報の文ハンドルへの戻り

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記述子およびロケータ は、データ固有の情報を保持する不透明なデータ構造です。

表2-2では、OCI記述子とそのCデータ型、およびその型の記述子をOCIDescriptorAlloc()のコール内で割り当てるOCI型定数を示しています。OCIDescriptorFree()関数は、記述子とロケータを解放します。

表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

シャード・キーおよびシャード・グループ・キー記述子

OCIShardkey

OCI_DTYPE_SHARD_KEY

注意:

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

次のリストでは、各記述子型の主な目的について説明しています。その後の各項では、各記述子型をより詳細に説明しています。

  • OCISnapshot: 文の実行時に使用

  • OCILobLocator: LOBコール(OCI_DTYPE_LOB)またはBFILEコール(OCI_DTYPE_FILE)で使用

  • OCIParam: 記述コールで使用

  • OCIRowid: ROWID値のバインドまたは定義で使用

  • OCIDateTimeおよびOCIInterval: 日時および時間隔データ型で使用

  • OCIComplexObjectComp: 複合オブジェクト検索で使用

  • OCIAQEnqOptionsOCIAQDeqOptionsOCIAQMsgPropertiesOCIAQAgent: アドバンスト・キューイングで使用

  • OCIAQNotify: パブリッシュ・サブスクライブ通知で使用

  • OCIServerDNs: LDAPベースのパブリッシュ・サブスクライブ通知で使用

スナップショット記述子

スナップショット記述子は、実行コールOCIStmtExecute()のオプション・パラメータです。

スナップショット記述子は、データベース・スナップショットに対する問合せが実行されることを示します。データベース・スナップショットは、ある特定の時点におけるデータベースの状態を表します。

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

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を渡すことによって割り当てられます。

注意:

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

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

パラメータ記述子

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

この情報は、記述操作を通して取得されます。

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

ROWID記述子

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

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

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

日付、日時および時間隔の記述子は、日付、日時または時間隔データ型(OCIDateOCIDateTimeおよびOCIInterval)を使用するアプリケーションにより使用されます。

これらの記述子は、バインドおよび定義で使用され、メモリーの割当ておよび解放を行う関数OCIDescriptorAlloc()およびOCIDescriptorFree()にパラメータとして渡されます。

複合オブジェクト記述子

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

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

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

データ固有の情報を保持するために使用するOracle Streamsアドバンスト・キューイング記述子がいくつか用意されています。

Oracle Streams アドバンスト・キューイングは、Oracle Databaseと統合されたメッセージ・キューイングです。

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

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

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

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

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

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

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

次の各項では、OCIアプリケーション開発の各ステップを詳細に説明します。

いくつかのステップは、オプションです。たとえば、文が問合せでない場合には、選択リスト項目を記述または定義する必要はありません。また、OCI関数のいずれか、またはすべてのステップ間で、アプリケーション固有の処理も発生します。

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

関連項目:

OCI環境の初期化

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

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

OCI環境の作成について

各OCI関数コールは、OCIEnvCreate()コールで作成された環境のコンテキスト内で実行されます。

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

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

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

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

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

これらの方法には次のものが含まれます。

注意:

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

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

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

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

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

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

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

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

注意:

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

例2-3 シングル・ユーザー・セッションのためのOCILogon2コールの使用

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

関連項目:

親プロセスによって作成された状態を子プロセスが再利用できるプロセス生成の機能を提供するオペレーティング・システムについては、「オペレーティング・システムの考慮事項」を参照してください。この項では、子プロセスが親によって作成されたものと同じデータベース接続を使用できない理由を説明します。

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

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

注意:

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

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

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

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

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

例2-4から例2-11までは、OCILogon2() (mode = OCI_DEFAULTを設定)、OCILogon()OCIAttrSet() (セッション・ハンドルの属性OCI_ATTR_USERNAMEを渡す)を指定したOCISessionBegin()などの関数で使用できる接続文字列を示しています。

例2-4では、DilbertとJoeが2人のローカル・データベース・ユーザーです。DilbertがJoeの代理ユーザーの役割を果たせるようにするには、例2-4に示すSQL文を使用します。

ユーザー名dilbertjoeの代理にするには、例2-5に示す接続文字列を使用します。(ユーザー名dilbertにはパスワードtiger123があります)。

左と右のカッコ([ と ]) は、接続文字列に入力します。

例2-6では、"Dilbert"と"Joe"が2人のローカル・データベース・ユーザーです。名前には大文字と小文字の区別があり、二重引用符で囲む必要があります。Dilbert"が"Joe"の代理ユーザーの役割を果たせるようにするには、例2-6に示すSQL文を使用します。

"Dilbert"を"Joe"の代理にするには、例2-7に示す接続文字列を使用します。必ず二重引用符(")を付けてください。

代理ユーザーが "dilbert[mybert]"として作成される場合、データベースに接続するには例2-8に示す接続文字列を使用します。(左と右のカッコ([ と ])は、接続文字列に入力します。)

例2-9では、dilbert[mybert]とjoe[myjoe]は、左右のカッコ([ と ])を含む2人のデータベース・ユーザーです。dilbert[mybert]がjoe[myjoe]の代理となるには、例2-9で示す接続文字列を使用します。

例2-10では、ALTER USER文を使用することによりターゲット・ユーザー名を設定できます。

関連項目:

注意:

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

例2-4 ローカル・ユーザーに別のユーザーの代理の役割を付与

ALTER USER joe GRANT CONNECT THROUGH dilbert;

例2-5 代理ユーザー用に使用する接続文字列

dilbert[joe]/tiger123@db1

例2-6 ローカル・ユーザーに別のユーザーの代理の役割を付与する際の大文字と小文字の区別の維持

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

例2-7 接続文字列での大文字と小文字の区別の維持

"Dilbert"["Joe"]/tiger123@db1

例2-8 接続文字列での"dilbert[mybert]"の使用

"dilbert[mybert]"/tiger123

rem the user was already created this way:
rem CREATE USER "dilbert[mybert]" IDENTIFIED BY tiger123;

例2-9 接続文字列での"dilbert[mybert]"["joe[myjoe]"]の使用

"dilbert[mybert]"["joe[myjoe]"]/tiger123

例2-10 ターゲット・ユーザー名の設定

ALTER USER joe GRANT CONNECT THROUGH dilbert;

次に、例2-11で示すように、OCIプログラムで、OCIAttrSet()コールを使用して属性OCI_ATTR_PROXY_CLIENTとプロキシdilbertを設定します。プログラム内で次の各文を使用して複数回接続を行います。

例2-11 OCIを使用したOCI_ATTR_PROXY_CLIENT属性および代理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);
プロキシを介さない複数のセッションまたは接続

プロキシを介さない複数のセッションまたは接続のオプションでは、明示的なアタッチ・コールおよびセッション開始コールを使用して、データベース接続で複数のユーザー・セッションおよび接続を維持します。

Oracle Databaseにアタッチし、セッションを開始するための具体的なコールは、次のとおりです。

  • OCIServerAttach(): OCI操作用のOracle Databaseへのアクセス・パスを作成します。

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

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

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

関連項目:

例2-12は、OCI環境の作成および初期化を示しています。

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

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

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

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

例2-12 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);
...
}

OCIでのSQL文の処理について

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

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

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

アプリケーションは、OCITransCommit()をコールすることにより、データベースへの変更をコミットします。

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

注意:

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

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

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

アプリケーションの終了について

終了する前にアプリケーションで実行される処理について説明します。

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

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

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

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

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

    注意:

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

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

関連項目:

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

注意:

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

OCIでのエラー処理

OCI関数コールには一連のリターン・コードが用意されています。

これらのOCI関数コールのリターン・コード(表2-3に記載)により、コールの成功または失敗(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

0

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

OCI_SUCCESS_WITH_INFO

1

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

OCI_NO_DATA

100

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

OCI_ERROR

-1

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

OCI_INVALID_HANDLE

-2

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

OCI_NEED_DATA

99

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

OCI_STILL_EXECUTING

-3123

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

OCI_CONTINUE

-24200

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

OCI_ROWCBK_DONE

-24201

このコードはコールバック関数からのみ戻されます。これは、コールバック関数がユーザー行のコールバックにより実行されていることを示します。

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

注意:

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

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

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

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

関連項目:

「標識変数」

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

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

NULL、切捨て以外

戻さない場合

OCI_SUCCESS

エラー = 0

OCI_SUCCESS

エラー = 0

インジケータ = 0

NULL、切捨て以外

戻す場合

OCI_SUCCESS

エラー = 0

リターン・コード = 0

OCI_SUCCESS

エラー = 0

インジケータ = 0

リターン・コード = 0

NULLデータ

戻さない場合

OCI_ERROR

エラー = 1405

OCI_SUCCESS

エラー = 0

インジケータ = -1

NULLデータ

戻す場合

OCI_ERROR

エラー = 1405

リターン・コード = 1405

OCI_SUCCESS

エラー = 0

インジケータ = -1

リターン・コード = 1405

切捨てデータ

戻さない場合

OCI_ERROR

エラー = 1406

OCI_ERROR

エラー = 1406

インジケータ = data_len

切捨てデータ

戻す場合

OCI_SUCCESS_WITH_INFO

エラー = 24345

リターン・コード = 1405

OCI_SUCCESS_WITH_INFO

エラー = 24345

インジケータ = data_len

リターン・コード = 1406

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

その他の値を戻す関数

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

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

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

オペレーティング・システムの考慮事項

オペレーティング・システムでは、子プロセスで親プロセスによって作成された状態を再利用できるプロセス生成機能が提供されている場合があります。

子プロセスの生成後、この子プロセスでは、親によって作成されたものと同じデータベース接続を使用できません。親と同じデータベース接続を子プロセスのために使用しようとすると、Oracle Netでは、データベースへの1つの接続を使用できるのは1つのユーザー・プロセスのみであるため、好ましくない接続障害が発生して、間欠的なORA-03137エラーが生じる可能性があります。

複数の同時接続が必要な場合、使用プラットフォームでスレッド・パッケージがサポートされていれば、スレッドの使用を検討します。シングル・スレッドまたはマルチ・スレッドのいずれのアプリケーションでも、同時接続はサポートされます。同時にオープンされる多数の接続によるパフォーマンス向上のため、それらのプーリングを検討してください。

パラメータの型

OCI関数には整数、ハンドル、文字列など、多様なデータ型のパラメータを使用することができます。

パラメータの型によっては注意事項があり、以降の項で説明します。

この項には次のトピックが含まれます:

関連項目:

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

アドレス・パラメータ

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

整数パラメータ

2進整数およびshort型2進整数パラメータは、サイズがシステムによって異なる数値です。システムでのこれらの整数のサイズは、ご使用のオペレーティング・システム用のOracle Databaseドキュメントを参照してください。

文字列パラメータ

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

注意:

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

列へのNULLの挿入

データベース列にNULLを挿入する方法について説明します。

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

  • 1つは、INSERT文またはUPDATE文のテキストの中でリテラルNULLを使用する方法です。たとえば、SQL文によりENAME列はNULLになります。

         INSERT INTO emp1 (ename, empno, deptno)
            VALUES (NULL, 8010, 20)
    
  • OCIバインド・コールでは、標識変数を使用します。

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

    注意:

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

関連項目

標識変数

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

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

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

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

この項には次のトピックが含まれます:

入力

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

入力インジケータ値 Oracle Databaseからのアクション

-1

Oracle DatabaseはNULLを列に割り当て、入力変数の値は無視します。

>=0

入力変数の値を列に割り当てます。

出力

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

出力インジケータ値 意味

-2

項目の長さが出力変数の長さよりも長いため、項目を切り捨てます。さらに、元の長さが、sb2標識変数で戻せる最大長より長くなっています。

-1

選択された値がNULLで、出力変数の値は変更されません。

0

完全な値をホスト変数に割り当てます。

>0

項目の長さが出力変数の長さよりも長いため、項目を切り捨てます。標識変数に戻された正の値は、切捨て前の実際の長さです。

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

リリース8.0より後に導入されたデータ型の標識変数は、前述の説明どおりに機能します。

例外はSQLT_NTY (名前付きデータ型)です。SQLT_NTY型のデータの場合、標識変数はインジケータ構造体へのポインタである必要があります。SQLT_REF型のデータでは、他の変数型と同様に、標準のスカラー・インジケータを使用します。

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

関連項目:

コールの取消しについて

長時間実行されたり繰り返されているOCIコールを取り消す方法について説明します。

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

注意:

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

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

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

注意:

OCIBreak()は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が行識別子が保存されているバッファである場合、新規給与をプレースホルダ:1にバインドし、rowidをプレースホルダ:2にバインドすることで、次のようなSQL文を後から処理できます。

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

rowid:2にバインドする場合は、必ずデータ型コード104 (ROWID記述子、表3-2を参照)を使用してください。

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

関連項目:

予約語

一部のワードはOracleによって確保されています。

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

この項には次のトピックが含まれます。「Oracle予約済ネームスペース」

関連項目:

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

Oracle予約済ネームスペース

表2-5は、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

OSN

TTC

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

Oracle Net RPCプロジェクト

Oracle Netディレクトリ

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

Oracle Net管理プロジェクト

Oracle Netインターチェンジ

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

Oracle Netドライバ

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

Oracle Net V1

Oracle Net 2タスク

GEN、L、ORA

コア・ライブラリ関数

LI、LM、LX

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

S

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

KO

カーネル・オブジェクト

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

OCIでのポーリング・モード操作

OCIには、完了をポーリングするコールがあります。そのようなポーリング・コードのコールの例は、次のとおりです。

このような場合、OCIでは、アプリケーションで必ず同じOCIコールがその接続で繰り返され、その間にその接続でそれ以外のことが行われないようにする必要があります。そのような接続でその他のOCIコールを実行すると(OCIが制御をコール元に戻した場合)、予期しない動作が生じる可能性があります。

したがって、コール元は、そのようなポーリング・モードのOCIコールにより、同じコールがその接続で繰り返され、そのコールが完了するまで他のことが行われないようにする必要があります。

OCIBreak()およびOCIReset()は、このルールに対する例外です。これらのコールは、開始されたOCIコールをコール元が停止できるように使用されます。

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

OCIでは、ブロック化モードまたは非ブロック化モードでサーバー接続を確立できます。

注意:

非ブロック化モードでは、コール元はコールが完了するまで、同じコールを繰り返す必要があるため、CPUの使用率が増加します。かわりに、マルチスレッド・モードを使用します。

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

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

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

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

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

  • LOBバッファリング

  • オブジェクト

  • 問合せキャッシュ

  • スクロール・カーソル

  • 透過的アプリケーション・フェイルオーバー(TAF)

  • OCIAQEnqArray()

  • OCIAQDeqArray()

  • OCIDescribeAny()

  • OCILobArrayRead()

  • OCILobArrayWrite()

  • OCITransStart()

  • OCITransDetach()

ブロック化モードの設定

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

OCI_ATTR_NONBLOCKING_MODE属性を設定できるのは、OCISessionBegin()またはOCILogon2()がコールされた後でのみです。それ以外の場合はエラーが戻されます。

注意:

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

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

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

OCIプログラムでのPL/SQL使用方法について

PL/SQLは、Oracleが開発したSQL言語の手続き型拡張機能です。

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

  • 1つまたは複数のSQL文

  • 変数宣言

  • 代入文

  • IF...THEN...ELSE文やループなどのプロシージャ型制御文

  • 例外処理

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

  • Oracleストアド・プロシージャおよびストアド・ファンクションのコール

  • 手続き型制御文を複数のSQL文と結合し、1つの単位として実行

  • 表、CURSOR FORループ、例外処理など、特殊なPL/SQL機能へのアクセス

  • カーソル変数の使用

  • サーバー内のオブジェクトの操作

    注意:

    • OCIで直接処理できるのは無名ブロックのみであり、名前付きパッケージまたは名前付きプロシージャは処理できないのに対し、プログラマは常にパッケージ・コールまたはプロシージャ・コールを無名ブロック内に入れ、そのブロックを処理できます。

    • OCIでPL/SQLの開始/終了ブロックを実行する前に、インジケータを-1に設定するかまたは実際の長さを0に設定して、すべてのOUT変数をNULLに初期化する必要があることに注意してください。

    • OCIでは、PL/SQL RECORDデータ型はサポートされていません。

    • OCIでPL/SQL VARCHAR2変数をバインドする場合、制御構造のオーバーヘッドにより、バインド変数の最大サイズは32512バイトです。

    注意:

    PL/SQLコードの作成時には、パーサーにより一対のハイフン「--」と改行文字との間のすべてがコメントとして処理されることを覚えておいてください。「--」を使用してコメントを各行に示した場合、Cコンパイラでは各行に改行「¥n」が挿入されず、すべての行がPL/SQLブロックで単一行として連結されます。この特定のケースでは、ある行がコメントで終わっている場合、パーサーは次の行のPL/SQLコード抽出に失敗してしまいます。この問題を回避するには、各「--」コメントの後に「\n」を入れ、そこでコメントが必ず終了するようにしてください。

    関連項目:

    PL/SQLブロックのコーディングの詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください

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

次の項では、ロケール情報の導出、文字列の操作、キャラクタ・セット変換、OCIメッセージなど、グローバリゼーションに使用されるOCI関数について説明します。

これらの関数には複数の目的および機能があるため、詳細は、このマニュアルの他の章を参照してください。

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

OCIEnvNlsCreate()関数は、NLS_LANGおよびNLS_NCHARの設定とは関係なく、アプリケーションでキャラクタ・セット情報を設定できます。

OCI_UTF16IDNLS_LANGまたはNLS_NCHARから設定できないため、OCIEnvNlsCreate()を使用して設定する必要があります。様々なクライアント側キャラクタ・セットIDおよび各国語キャラクタ・セットIDを使用して、同じシステム環境内で初期化した複数の環境ハンドルを1つのアプリケーションで使用できます。たとえば、次のようにします。

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

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

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

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

関連項目:

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

OCIインタフェースによる文字制御の実行方法について説明します。

OCINlsGetInfo()関数は、その値がOCIEnvNlsCreate()で使用されている場合に、OCI_UTF16IDなどの任意のキャラクタ・セットに関する情報を戻します。

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

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

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

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

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

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

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

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

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

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

OCIによるキャラクタ・セットのサポート方法について説明します。

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

OCIの言語および地域の制御

NLSの言語および地域は、OCI環境ハンドルでOCI_ATTR_ENV_NLS_LANGUAGEOCI_ATTR_ENV_NLS_TERRITORY属性を使用することにより、プログラム的に設定することもできます。使用方法の詳細は、「OCI_ATTR_ENV_NLS_LANGUAGE」および「OCI_ATTR_ENV_NLS_TERRITORY」を参照してください。これらの属性は、設定後にその環境ハンドルから作成されたデータベース・セッションに関して有効になります。

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

グローバリゼーション・サポート関数は、環境ハンドルまたはユーザー・セッション・ハンドルを受け入れます。

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

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

関連項目:

OCIでのロケール情報の取得について

Oracle Databaseロケールは、言語、地域およびキャラクタ・セット定義で構成されます。

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

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

  • 曜日(翻訳済)

  • 曜日の略称(翻訳済)

  • 月名(翻訳済)

  • 月名の略称(翻訳済)

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

  • AM/PM (翻訳済)

  • AD/BC (翻訳済)

  • 数値書式

  • 借方/貸方

  • 日付書式

  • 通貨書式

  • デフォルトの言語

  • デフォルトの地域

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

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

  • デフォルト・カレンダ

例2-13のコードでは、ロケール情報を取得し、エラーをチェックします。

例2-13 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およびBOM (バイト・オーダー・マーク)について

OCIでは、BOM (バイト・オーダー・マーク)がサポートも処理もされず、バイト・オーダーがアプリケーションが実行されているマシンにネイティブであるとみなされます。

使用するOCIアプリケーションでは、OCIが文字列のエンコードを検出できると想定されるBOMを含む文字列は渡されません。OCIアプリケーションでは、渡される文字列にBOMが存在する場合はそれを削除する必要があり、それがOCIの機能で想定されるエンコードであるようにする必要があります。

OCIでの文字列操作について

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

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

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

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

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

  • 文字の分類

  • 大/小文字の変換

  • 表示長の計算

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

例2-14では、単純な文字列操作の例を示します。

OCI文字分類関数については、「OCI文字分類関数」で詳しく説明します。

例2-15では、OCIでの文字の分類方法を示します。

例2-14 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);
}

例2-15 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アドレスで揃える必要があり、揃っていない場合、エラーが発生します。

例2-16では、Unicodeへの単純な変換を示します。

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

/* 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 Databaseメッセージを取得するための単純なインタフェースを提供します。

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

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

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関数に戻すことができます。

Imsgenユーティリティの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 Databaseメッセージ・テキスト・ファイルの例を次に示します。

/ 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