プライマリ・コンテンツに移動
Pro*C/C++プログラマーズ・ガイド
12c リリース1(12.1)
B71397-03
目次へ移動
目次
索引へ移動
索引

前
次

Oracle拡張機能

この項では、次の拡張機能を説明します。

参照セマンティクス

ANSI規格では、構文が指定されています。パフォーマンス向上のために、Oracleではこの規格を拡張して参照セマンティクスを導入しています。

値構文では、ホスト変数データのコピーを作成します。参照セマンティクスでは、ホスト変数のアドレスを使用し、コピーは行いません。そのため、参照セマンティクスを使用すると、大量データ処理のパフォーマンスが向上します。

フェッチの速度向上には、データ句の前にREFキーワードを使用します。

EXEC SQL SET DESCRIPTOR 'out' VALUE 1 TYPE = :ename_type,
   LENGTH = :ename_len, REF DATA = :ename_data ;
EXEC SQL DESCRIPTOR 'out' VALUE 2 TYPE = :empno_type,
   LENGTH = :empno_len, REF DATA = :empno_data ;

これにより、取り出された結果がホスト変数に渡されます。GET文は必要ありません。FETCHが実行されるたびに、取り出されたデータは、ename_dataおよびempno_dataに直接書き込まれます。

次のコード例に示すように、REFキーワードが使用できるのは、DATA、INDICATORおよびRETURNED_LENGTH項目(フェッチする行によって変わる可能性があります)の前に限られます

int indi, returnLen ;
...
EXEC SQL SET DESCRIPTOR 'out' VALUE 1 TYPE = :ename_type,
   LENGTH = :ename_len, REF DATA = :ename_data,
      REF INDICATOR = :indi, REF RETURNED_LENGTH = :returnLen ;

フェッチするたびに、returnLenによりenameフィールドの実際に取得した長さが保持されます。このフィールドはCHARまたはVARCHAR2データで使用すると便利です。

ename_lenには取り出された長さは渡されません。これは、FETCH文によって変更されません。データの行をフェッチする前に列の最大幅を調べるには、GET文の前にDESCRIBEを使用します。

REFキーワードは、SELECT以外のSQL文の処理速度向上のためにも使用します。参照セマンティクスの場合、記述子領域にコピーされた値ではなくホスト変数が使用されます。SQL文を実行する時点でのホスト変数データが使用されるのであって、SETの時点でのデータではありません。次はその例です。

int x = 1 ;
EXEC SQL SET DESCRIPTOR 'value' VALUE 1 DATA = :x ;
EXEC SQL SET DESCRIPTOR 'reference' VALUE 1 REF DATA = :x ;
x = 2 ;
EXEC SQL EXECUTE s USING  DESCRIPTOR 'value' ;    /* Will use  x = 1 */
EXEC SQL EXECUTE s USING DESCRIPTOR 'reference' ; /* Will use x = 2 */

関連項目:

違いの詳細は、SET DESCRIPTORを参照してください。

配列を使用したバルク操作について

Oracleによりバルク操作機能が追加され、ANSI動的SQLが拡張されました。バルク操作を行うには、処理する入力データ量または行数を指定するために、FOR句で配列サイズを指定します。

FOR句は、ALLOCATE文で最大データ量または最大行数の指定に使用します。最大配列サイズ100を指定するには、次のように記述します。

EXEC SQL FOR 100 ALLOCATE DESCRIPTOR 'out' ;

または

int array_size = 100 ;
...
EXEC SQL FOR :array_size ALLOCATE DESCRIPTOR 'out' ;

FOR句は、記述子にアクセスする後続の文で使用されます。次に示すように、出力記述子では、ALLOCATE文で指定した配列サイズと等しいか、それよりも小さい配列サイズをFETCH文に割り当てる必要があります。

EXEC SQL FOR 20 FETCH c1 USING DESCRIPTOR 'out' ;

後続の、同じ記述子のDATA、INDICATORまたはRETURNED_LENGTH値を取得するGET文では、FETCH文と同じ配列サイズを指定する必要があります。

int val_data[20] ;
short val_indi[20] ;
...
EXEC SQL FOR 20 GET DESCRIPTOR 'out' VALUE 1 :val_data = DATA,
  :val_indi = INDICATOR ;

ただし、LENGTH、TYPE、COUNTなど、行によって変化しない項目を参照するGET文では、FOR句は使用しないでください

int cnt, len ;
...
EXEC SQL GET DESCRIPTOR 'out' :cnt = COUNT ;
EXEC SQL GET DESCRIPTOR 'out' VALUE 1 :len = LENGTH ;

これは、参照セマンティクスを使用したSET文でも同じです。FETCHの前にあり、DATA、INDICATORまたはRETURNED_LENGTHに対する参照セマンティクスを使用したSET文には、FETCHと同じ配列サイズを指定する必要があります。

int ref_data[20] ;
short ref_indi[20] ;
...
EXEC SQL FOR 20 SET DESCRIPTOR 'out' VALUE 1 REF DATA = :ref_data,
   REF INDICATOR = :ref_indi ;

同様に、行のバッチの挿入など、入力に使用する記述子でも、ALLOCATE文で使用した配列サイズと等しいか、それよりも小さいサイズの配列サイズをEXECUTEまたはOPEN文に使用する必要があります。値および参照セマンティクスのどちらも、DATA、INDICATORまたはRETURNED_LENGTHにアクセスするSET文では、EXECUTE文と同じ配列サイズを使用する必要があります。

FOR句は、DEALLOCATEまたはPREPARE文では使用しません。

次のコード例に、出力記述子のないバルク操作の例を示します(出力はなく、表empに挿入する入力のみあります)。COUNTの値は2です(INSERT文にename_arrおよびempno_arrの2つのホスト変数があることを示します)。データ配列ename_arrには、順番に「Tom」、「Dick」および「Harry」という3つの文字列が保持されています。インジケータ配列ename_indには2つ目の要素に-1の値を設定しているため、「Dick」ではなくNULLが挿入されます。データ配列empno_arrには、従業員番号が3つ含まれています。DML RETURNING句を使用すると、実際に挿入された名前を確認できます。

...
char* dyn_statement = "INSERT INTO emp (ename) VALUES (:ename_arr)" ;
char ename_arr[3][6] = {Tom","Dick","Harry"} ;
short ename_ind[3] = {0,-1,0} ;
int ename_len = 6, ename_type = 97, cnt = 2 ;
int empno_arr[3] = {8001, 8002, 8003} ;
int empno_len = 4 ;
int empno_type = 3 ;
int array_size = 3 ;
EXEC SQL FOR :array_size ALLOCATE DESCRIPTOR 'in' ;
EXEC SQL SET DESCRIPTOR 'in' COUNT = :cnt ;
EXEC SQL SET DESCRIPTOR 'in' VALUE 1 TYPE = :ename_type, LENGTH = :ename_len ;
EXEC SQL SET DESCRIPTOR 'in' VALUE 2 TYPE = :empno_type, LENGTH = :empno_len ;
EXEC SQL FOR :array_size SET DESCRIPTOR 'in' VALUE 1
   DATA = :ename_arr, INDICATOR = :ename_ind ;
EXEC SQL FOR :array_size SET DESCRIPTOR 'in' VALUE 2
   DATA = :empno_arr ;
EXEC SQL PREPARE s FROM :dyn_statement ;
EXEC SQL FOR :array_size EXECUTE s USING DESCRIPTOR 'in' ;
...

上のコードを実行すると、次の値が挿入されます。

EMPNO   ENAME
 8001   Tom
 8002   
 8003   Harry

関連項目:

構造体配列のサポート

HOST_STRIDE_LENGTHを構造体のサイズに、INDICATOR_STRIDE_LENGTHをインジケータ構造体のサイズに、そしてRETURNED_LENGTH_STRIDEを戻された長さの構造体のサイズに設定する必要があります。

構造体の配列は、ANSI動的SQLによってサポートされていますが、従来のOracle動的SQLではサポートされていません

関連項目:

表14-5

オブジェクト型のサポート

独自に定義したオブジェクト型では、Oracle TYPEを108にして使用してください。オブジェクト型の列では、DESCRIBE文を使用してUSER_DEFINED_TYPE_VERSION、USER_DEFINED_TYPE_NAME、USER_DEFINED_TYPE_NAME_LENGTH、USER_DEFINED_TYPE_SCHEMAおよびUSER_DEFINED_TYPE_SCHEMA_LENGTHを取得します。

DESCRIBE文を使用しないでこれらの値を取得する場合は、SET DESCRIPTOR文を使用して自分で設定を行う必要があります。