TimesTenのPro*C/C++での機能

この項では、TimesTenでのPro*C/C++で使用できるその他の機能について説明します。

TimesTenのPro*C/C++での連想配列バインド

連想配列は、PL/SQLブロックとPro*C/C++アプリケーション間だけでなく、OCIアプリケーション間でも渡すことができます。これらには、BINARY_INTEGER型またはPLS_INTEGER型のPL/SQL変数によって索引付けができます。

「TimesTenのOCIでの連想配列のバインド」の説明のとおり、TimesTenのPL/SQLでの連想配列(以前の索引付き表またはPL/SQL表)は、INOUTまたはIN OUTバインド・パラメータとしてサポートされています。詳細および制限事項は、該当する項を参照してください。

通常は、ホスト配列全体がPL/SQLに渡されますが、Pro*C/C++のARRAYLEN文を使用すれば、より小さい配列サイズを指定できます。

『Pro*C/C++プログラマーズ・ガイド』埋込みPL/SQLでPL/SQL表、ホスト配列およびARRAYLEN文に関する説明を参照してください。

次のコードの抜粋では、配列salary[]がPro*C/C++からPL/SQLの連想配列num_tabにバインドされています。

...
float salary[100];
/* populate the host array */
EXEC SQL EXECUTE
  DECLARE
    TYPE NumTabTyp IS TABLE OF REAL
                   INDEX BY BINARY_INTEGER;
    median_salary REAL;
    n BINARY_INTEGER;
...
  FUNCTION median (num_tab NumTabTyp, n INTEGER)
    RETURN REAL IS
  BEGIN
    -- compute median
  END;
  BEGIN
    n := 100;
    median_salary := median(:salary, n);
    ...
  END;
END-EXEC;
...

TimesTen Pro*C/C++でのLOB

TimesTen ClassicではLOB (ラージ・オブジェクト)がサポートされています。これには、CLOB(Character LOB)、NCLOB(National Character LOB)およびBLOB(Binary LOB)が含まれます。

この項では、主要なPro*C/C++ LOBの機能およびTimesTen固有のサポートおよび制限に重点を置いています。

内容は次のとおりです。

追加情報は、次の項を参照してください。

  • 「ラージ・オブジェクト(LOB)」。この項はODBC向けですが、LOBの概要、TimesTenとOracle Database LOBの違いおよびLOBのプログラミング・インタフェースについても説明しています。

  • LOBロケータ、一時LOB、OCIでの簡易データ・インタフェースまたはLOBロケータ・インタフェースの使用、およびOCIのLOBのその他の機能については、「TimesTen OCIでのLOB」を参照してください。

  • TimesTenでのLOBに関する追加情報は、『Oracle TimesTen In-Memory Database SQLリファレンス』LOBのデータ型を参照してください。

  • LOB、およびPro*C/C++でのその使用方法の詳細は、『Pro*C/C++プログラマーズ・ガイド』LOBを参照してください。TimesTenではBFILE、SecureFile、LOBに対する配列読取りおよび書込み、またはLOBのコールバック関数はサポートされていないということを覚えておいてください。特に、その章にある、プログラムでのLOBの使用に関する説明を参照してください。

ノート:

  • OCIについての章で説明するとおり、TimesTenでは、アプリケーションで使用したLOBは、トランザクションの終了後は有効ではありません。

  • TimesTenでは、LOBのピース単位のデータ・インタフェースはOCIまたはPro*C/C++アプリケーションには適用されません。(ただし、LOBロケータ・インタフェースの機能を介して、LOBデータを分割して操作することはできます。)

Pro*C/C++でのLOB簡易データ・インタフェースの使用

簡易データ・インタフェースでは、その他のスカラー・データ型の操作(EXEC SQL INSERTEXEC SQL SELECTの使用など)と同様の方法で、アプリケーションによるLOBデータの操作が可能です。アプリケーションでは、対応する変数タイプと互換性のあるLOB型を使用できます。

アプリケーションでは、必要に応じてEMPTY_BLOB()関数またはEMPTY_CLOB()関数を使用して、永続LOBを初期化できます。これは、次に説明する、LOBロケータ・インタフェースでALLOCATEを使用することとほぼ同じです。次のような表について考えてみます。

EXEC SQL CREATE TABLE lob_table ( a_blob BLOB, a_clob CLOB );
...
EXEC SQL INSERT INTO lob_table (a_blob, a_clob) 
                VALUES (EMPTY_BLOB(), EMPTY_CLOB());
...
EXEC SQL CREATE TABLE data_table
         ( name VARCHAR2(30), length NUMBER(10), bincol BLOB, charcol CLOB );

次の例では、data_tableから選択したLOBデータをmyblobおよびmyclobに代入し、次に、代入したLOBデータをlob_tableに挿入します。

...
OCIBlobLocator *myblob;
OCIClobLocator *myclob;
...
EXEC SQL SELECT bincol, charcol INTO :myblob, :myclob FROM data_table 
                WHERE name = :key;
...
// Put data into lob_table.
...
EXEC SQL INSERT INTO lob_table (a_blob, a_clob) VALUES (:myblob, :myclob);

NCLOBを使用するには、次のように変数を宣言します。

OCIClobLocator CHARACTER SET IS NCHAR_CS *mynclob;

ノート:

OCIまたはPro*C/C++を介した簡易データ・インタフェースでは、バインドのサイズが64KBに制限されます。

Pro*C/C++でのLOBロケータ・インタフェースの使用

Pro*C/C++ LOBロケータ・インタフェースは、データベースまたは一時LOB(ピース単位またはチャンク全体)のどちらとも使用できます。

LOBに関するPro*C/C++文の詳細は、『Pro*C/C++プログラマーズ・ガイド』LOB文を参照してください。TimesTenではBFILE、SecureFile、LOBに対する配列読取りおよび書込み、またはLOBのコールバック関数の専用の機能はサポートされていないことに留意してください。

エンドツーエンドの例は、『Pro*C/C++プログラマーズ・ガイド』lobdemo1.pcを参照してください。

「OCIでのLOBロケータ・インタフェースの使用について」も参照してください。

ヒント:

Pro*C/C++構文で、機能性が十分でないために操作を完了するための指定を完全に行えない場合は、対応するOCI関数を代替として使用できます。

Pro*C/C++では、アプリケーションで、最初にALLOCATEを使用してロケータを割り当ててから、CREATE TEMPORARY埋込みSQL機能を使用して一時LOBを作成できます。FREEを使用してロケータへの割当てを解放し、FREE TEMPORARYを使用して一時LOB自身を解放します。これを次に示します。

「OCIでの一時LOBの作成」も参照してください

ヒント:

TimesTenでは、一時LOBを作成すると、データベース・トランザクションがまだ進行していない場合は、データベース・トランザクションが作成されます。エラーとなる状況を回避するには、コミットまたはロールバックを実行してトランザクションをクローズしてください。

OCIClobLocator *tempclob;
EXEC SQL ALLOCATE :tempclob;
EXEC SQL LOB CREATE TEMPORARY :tempclob;
...
// (Manipulate LOB as desired.)
...
EXEC SQL FREE TEMPORARY :tempclob;
EXEC SQL FREE :tempclob;

あるいは、LOB文字セット(ここではNCHAR)を指定するには、対応するOCI関数を使用できます。

status = OCILobCreateTemporary(svc, err, tempclob, OCI_DEFAULT, SQLCS_NCHAR,
         OCI_TEMP_CLOB, TRUE, OCI_DURATION_TRANSACTION);

Pro*C/C++で永続LOBのロケータにアクセスする場合、アプリケーションは通常、SQL文を使用してロケータを取得し、適切なAPI関数にそれを渡すことで、データベースからLOBにアクセスします。

前述の『Pro*C/C++プログラマーズ・ガイド』lobdemo1.pcにある例からの抜粋を次に示します。この例では、CLOB license_txtおよび社会保険番号、氏名、および交通違反を集計したテキストが含まれる列(CLOB列)で構成される表license_tableを使用します。「OCIでの永続LOBのロケータへのアクセス」も参照してください。

OCIClobLocator *license_txt;
...
EXEC SQL ALLOCATE :license_txt;
...
EXEC SQL SELECT name, txt_summary INTO :name, :license_txt FROM license_table
                WHERE sss = :sss;

LOBロケータ・インタフェースを使用してLOBデータの読取りと書込みを行う場合、Pro*C/C++アプリケーションでは、LOBをオープンおよびクローズするにはLOB OPENおよびLOB CLOSE、LOBデータを読み取るにはLOB READ、LOBデータに書き込むか追加するにはLOB WRITEまたはLOB WRITE APPEND、LOBに関する情報を取得するにはLOB DESCRIBE、その他様々な操作を実行するには他の各種Pro*C/C++機能を使用できます。Pro*C/C++のLOBロケータ・インタフェースのすべての機能については、『Pro*C/C++プログラマーズ・ガイド』LOBを参照してください。このドキュメント内の『OCIのLOBロケータ・インタフェースを使用したLOBデータの読取りおよび書込み」も参照してください。

データを書き込むには、LOB WRITE ONEを使用して、1チャンクでデータを書き込みます。TimesTenでは、LOB WRITE FIRSTLOB WRITE NEXTまたはLOB WRITE LAST(ピース単位のデータ・インタフェースの機能)はサポートしていません。

EXEC SQL LOB READ文の例を次に示します。

EXEC SQL LOB READ :amt FROM :blob INTO :buffer;

追加情報は、『Pro*C/C++プログラマーズ・ガイド』BLOBのREAD、ファイルの書込みの例を参照してください。

EXEC SQL LOB WRITE文の例(LOBデータの1チャンクでの書込み)を次に示します。

EXEC SQL LOB WRITE ONE :amt FROM :buffer INTO :blob;

『Pro*C/C++プログラマーズ・ガイド』ファイルの読取り、BLOBのWRITEの例を参照してください。

EXEC SQL LOB WRITE APPEND文の例を次に示します。

EXEC SQL LOB WRITE APPEND :amt FROM :writebuf INTO :blob;

ノート:

LOBをオープンすることは、概念的にはファイルを開くことに似ていますが、技術的には異なります。LOBをオープンすることは、必要となるリソースに関するヒントのようなものです。

OCILobRead()OCILobWrite()または同等の機能によってアクセスされているLOBは、必要に応じて自動的にオープンされます。

前述の『Pro*C/C++プログラマーズ・ガイド』lobdemo1.pcにある例からの抜粋を次に示します。

...
OCIClobLocator *a_clob;
char *charbuf;
ub4 ClobLen, WriteAmt;
int CharLen = strlen(charbuf);
int NewCharbufLen = CharLen + DATELENGTH + 4;
varchar *NewCharbuf;
NewCharbuf = (varchar *)malloc(2 + NewCharbufLen);
NewCharbuf->arr[0] = '\n';
NewCharbuf->arr[1] = '\0';
strcat((char *)NewCharbuf->arr, charbuf);
NewCharbuf->arr[CharLen + 1] = '\0';
strcat((char *)NewCharbuf->arr, curdate);
NewCharbuf->len = NewCharbufLen;
EXEC SQL LOB DESCRIBE :a_clob GET LENGTH INTO :ClobLen;
WriteAmt = NewCharbufLen;
EXEC SQL LOB WRITE ONE :WriteAmt FROM :NewCharbuf WITH LENGTH :NewCharbufLen 
                       INTO :a_clob;
...

次の例では、前述の例と同様に、LOB WRITE ONEを使用します。次にLOB WRITE APPENDも使用して、その他のデータを追加します。ここでは、MAX_CHUNKSに達するまで、1KずつのチャンクでBLOBに書込みまたは追加を行います。

...
 EXEC SQL select b into :blob from t where pk = 1 for update;
 EXEC SQL LOB OPEN :blob READ WRITE;
 
 // Write/append to the BLOB
 for (i = 0; i < MAX_CHUNKS; i++) {
   if (i==0) { // FIRST CHUNK
     /*
     Write the first piece
     */
     EXEC SQL LOB WRITE ONE :amt FROM :writebuf INTO :blob;
 
   }
   else { // All Other Chunks
     /*
     At this point, APPEND all the next pieces
     */
     EXEC SQL LOB WRITE APPEND :amt FROM :writebuf INTO :blob ;
   }
   ...
 }
...