Hitachi

ノンストップデータベース HiRDB Version 10 UAP開発ガイド


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