この項では、次の拡張機能を説明します。
SET文のデータ項目の参照セマンティクス。
バルク操作のための配列。
オブジェクト型、NCHAR列およびLOBのサポート。
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
関連項目:
制限および注意事項については、FOR句の使用方法についてを参照してください。
HOST_STRIDE_LENGTHを構造体のサイズに、INDICATOR_STRIDE_LENGTHをインジケータ構造体のサイズに、そしてRETURNED_LENGTH_STRIDEを戻された長さの構造体のサイズに設定する必要があります。
構造体の配列は、ANSI動的SQLによってサポートされていますが、従来のOracle動的SQLではサポートされていません。
関連項目: