18.3.8 カーソルによる検索の記述
SQLJにはDECLARE CURSOR,OPEN文,及びCLOSE文がないため,カーソルの宣言,オープン,及びクローズは,Javaの命令として記述します。このとき,カーソル名の代わりに反復子オブジェクトを使用します。反復子オブジェクトは,オブジェクトへの参照変数として宣言されるため,名称規則と有効範囲についてはJavaの規則に従います。
検索結果の取得は,使用する反復子オブジェクトの型によって,FETCH文で取得する方法と,FETCH文を使用しない方法とがあります。FETCH文では,位置指定反復子型のオブジェクトを使用し,列名指定反復子のオブジェクトは使用できません。
(1) FETCH文を使用した検索
FETCH文を使用して検索をする場合の,記述方法について説明します。
(a) 位置指定反復子クラスの定義と反復子オブジェクトの宣言
-
スタンダードインタフェース版の場合
スタンダードインタフェース版の場合,位置指定反復子のクラスを定義して,反復子オブジェクトを宣言します。クラス名はJavaの識別子です。データ型Nは,FETCH文でN番目の検索項目を格納するJavaの変数のデータ型です。
#sql 修飾子 iterator クラス名 (データ型1,データ型2,…) ; 修飾子 クラス名 反復子オブジェクト ;
-
ネイティブインタフェース版の場合
ネイティブインタフェース版の場合,次のようになります。
#sql 修飾子 iterator クラス名 [ implements JP.co.Hitachi.soft.HiRDB.pdjpp.runtime.ForUpdate ] [ with キーワード=設定値,…] (データ型1,データ型2,…) ; 修飾子 クラス名 反復子オブジェクト ;
UPDATE文,DELETE文で反復子を使用する場合,JP.co.Hitachi.soft.HiRDB.pdjpp.runtime.ForUpdateインタフェースを継承します。
WITH句のキーワードは,反復子の機能を示します。設定値は定数だけです。WITH句のキーワードと値の組み合わせを次の表に示します。
表18‒7 WITH句のキーワードと値の組み合わせ WITH句のキーワード
機能
設定値
holdability
ホールダブルカーソルであることを示します。
TRUE
updateColumns
更新する列を示します。
"列名,列名,…"
(b) カーソルの定義とオープン
宣言した反復子オブジェクトに,SELECT文の結果セットを代入します。
#sql [コンテキスト] 反復子オブジェクト = { SELECT文 } ;
(c) 検索結果の取り出し
カーソル名の代わりに,反復子オブジェクトを指定してFETCH文を実行します。反復子オブジェクトは,先頭にコロンを付けます。
#sql [コンテキスト] { FETCH :反復子オブジェクト INTO :変数1,:変数2,…} ;
(d) NOT FOUNDの判定
反復子オブジェクトのendFetchメソッドを呼び出して,NOT FOUNDかどうかを判定します。検索する行がない場合はtrueが返ります。次の行がある場合はfalseが返ります。カーソルを閉じた後に呼んだ場合はtrueが返ります。
while(! 反復子オブジェクト.endFetch()) { 取り出した行に対する処理 }
(e) カーソルのクローズ
カーソルをクローズする場合は,closeメソッドを呼び出します。
反復子オブジェクト.close() ;
FETCH文を使用した検索例を次に示します。
#sql public iterator ByPos(String, int); : { ByPos positer; String name = null; int code = 0; #sql positer = { SELECT SNAME,SCODE FROM ZAIKO }; #sql { FETCH :positer INTO :name,:code }; while( !positer.endFetch() ){ System.out.println(name + ":" + code); #sql { FETCH :positer INTO :name,:scode }; } positer.close(); }
(2) FETCH文を使用しない検索
列名指定反復子のフィールドを使用して,検索結果の各列を読み出します。
(a) 列名指定反復子クラスの定義
検索項目と同じ名称(大文字と小文字は区別しない)を,クラスのフィールドとして定義します。データ型は,検索結果を受け取るJavaの変数のデータ型を指定します。なお,ネイティブインタフェースの場合は使用できません。
検索項目が,値式,Javaで使用できない文字を含む列名などの場合,AS句で検索項目に別名を定義しておいて,その別名を使用します。
#sql 修飾子 iterator クラス名 (データ型1 列名1, データ型2 列名2,…) ; 修飾子 クラス名 反復子オブジェクト;
(b) カーソルの定義とOPEN
宣言した反復子オブジェクトに,SELECT文の結果セットを代入します。
#sql [コンテキスト] 反復子オブジェクト = { SELECT文 } ;
(c) 次の行の取り出しとNOT FOUNDの判定
反復子オブジェクトのnextメソッドを呼び出して,NOT FOUNDかどうかを判定します。NOT FOUNDの場合はTRUEが返ります。行がある場合はFALSEが返ります。カーソルがオープンした後,最初のnextメソッドが実行されるまで,カーソルは検索結果の最初の行に位置づけられません。
while(反復子オブジェクト.next()){ 取り出した行に対する処理 }
(d) 検索結果の取得
反復子オブジェクトの各フィールドから,データを読み出します。NOT FOUNDの場合や,カーソルがクローズされた後に読み出すと,結果は不定となります。フィールドのデータ型がJavaの基本データ型で,検索結果がナル値の場合に読み出すと,SQLNullExceptionオブジェクトが発生します。
フィールドに対して代入しても,データベースには反映されません。
変数1 = 反復子オブジェクト.列名1 ; 変数2 = 反復子オブジェクト.列名2 ; :
(e) カーソルのCLOSE
反復子オブジェクトのcloseメソッドを呼び出します。
反復子オブジェクト.close() ;
FETCH文を使用しない検索例を次に示します。
(例)
#sql public iterator ByName(String sname, int scode); : { ByName nameiter; String s; int i; #sql nameiter = { SELECT SNAME, SCODE FROM ZAIKO }; while( nameiter.next() ){ s = nameiter.sname(); i = nameiter.scode(); System.out.println(s + ":" + i); } nameiter.close(); }
(3) カーソルを使った更新
ネイティブインタフェース版の場合,カーソルを使った更新ができます。
UPDATE文,DELETE文で,カーソルが位置づけられている行を操作する場合,カーソル名の代わりに反復子を指定します。なお,反復子のクラス定義のときに,必ずForUpdateインタフェースを継承しておく必要があります。
#sql [コンテキスト] { DELETE文 WHERE CURRENT OF :反復子オブジェクト } ; #sql [コンテキスト] { UPDATE文 WHERE CURRENT OF :反復子オブジェクト } ;
反復子を使用した更新例を次に示します。
#sql public iterator ByPos implements JP.co.Hitachi.soft.HiRDB.pdjpp.runtime.ForUpdate (String, int); : { ByPos positer; String name = null; int year = 0; int newyear; #sql positer = { SELECT FULLNAME, BIRTHYEAR FROM PEOPLE }; #sql { FETCH :positer INTO :name,:year }; while( !positer.endFetch() ){ newyear=year+10; #sql { UPDATE PEOPLE SET YEAR=:newyear WHERE CURRENT OF :positer; }; } positer.close(); }