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();
}