Hitachi

ノンストップデータベース HiRDB Version 10 SQLリファレンス


7.7.1 FOR文の形式と規則

〈この項の構成〉

(1) 機能

表の各行に対してSQL文の実行を繰り返します。

(2) 形式

 〔開始ラベル:〕
 FOR ループ変数名 AS
  〔カーソル名 CURSOR 〔WITH HOLD〕FOR〕 
     カーソル指定 形式1
  〈排他オプション〉
   〔〔{WITH {SHARE|EXCLUSIVE}LOCK
     |WITHOUT LOCK〔{WAIT|NOWAIT}〕}〕
   〔{WITH ROLLBACK|NO WAIT}〕〕
     〔FOR{UPDATE 〔OF列名〔,列名〕…〕〔NOWAIT〕|READ ONLY}〕
     〔UNTIL DISCONNECT〕
  DO
  SQL手続き文;〔SQL手続き文;〕…
 END FOR 〔終了ラベル〕

(3) オペランド

(a) 〔開始ラベル〕

FOR文の文ラベルを指定します。

(b) ループ変数名

暗黙的に宣言するSQL変数の修飾子を指定します。

FOR文実行時,カーソル指定の導出列名を変数名とするSQL変数が暗黙的に宣言されます。暗黙的に宣言されたSQL変数はループ変数名での修飾ができます。

ループ変数名はラベル名の規則に従います。したがって,ラベル名に関する制限はループ変数名に対しても適用されます。

(c) カーソル名

カーソルの名称を指定します。

カーソル名を省略した場合は,HiRDBが固有のカーソル名を生成します。

カーソル名については,「名前の指定」を参照してください。

(d) 〔WITH HOLD〕

ホールダブルカーソルを使用する場合に指定します。

WITH HOLDは,UNTIL DISCONNECTを指定した場合の機能と同じなので,説明はUNTIL DISCONNECTを参照してください。また,この指定がUNTIL DISCONNECTと重複しているかどうかによる機能差はありません。

ホールダブルカーソルに関する制限事項については,「DECLARE CURSOR 形式1(カーソル宣言)」を参照してください。

(e) カーソル指定 形式1

問合せの内容を表すカーソルを指定します。

カーソル指定については「カーソル指定 形式1」を参照してください。

FOR文で指定するカーソル指定の規則
  • 導出列に名前のない列は指定できません。名前のない列を導出列として指定する場合は,AS句を指定し,導出列に対して別名を付与してください。

  • 導出列名が重複する導出列を指定できません。

  • 導出列に〔表指定.〕ROWを指定できません。

  • 導出列に,FROM句に平坦化の指定がない添字なし繰返し列を指定できません。

カーソル指定の導出列が次に示す項目から導き出された列で,AS 列名を省略した場合,その列は名前のない列となります。導出列がスカラ副問合せの場合,導出列名はスカラ副問合せの選択式の導出列名に依存します。

  • スカラ演算(ウィンドウ関数を含む)

  • 関数呼出し

  • 集合関数

  • 定数

  • USER値関数

  • CURRENT_DATE値関数

  • CURRENT_TIME値関数

  • CURRENT_TIMESTAMP値関数

  • コンポネント指定

  • GET_JAVA_STORED_ROUTINE_SOURCE指定

  • WRITE指定

  • SQL変数

  • SQLパラメタ

(f) 排他オプション

問合せをする場合の排他制御モードと,ほかのユーザが資源を占有していた場合の処置を指定します。

排他オプションについては,「排他オプション」を参照してください。

(g) 〔FOR{UPDATE 〔OF列名〔,列名〕…〕〔NOWAIT〕|READ ONLY}〕

FOR UPDATE 〔OF列名〔,列名〕…〕をFOR UPDATE句といいます。

FOR UPDATE句,及びFOR READ ONLYについては,「DECLARE CURSOR 形式1(カーソル宣言)」を参照してください。

(h) 〔UNTIL DISCONNECT〕

ホールダブルカーソルを使用する場合に指定します。

この指定をしたときの機能は,WITH HOLDを指定した場合と全く同じです。また,この指定がWITH HOLDと重複しているかどうかによっての機能差はありません。

また,ホールダブルカーソルに関する制限事項については,「DECLARE CURSOR 形式1(カーソル宣言)」を参照してください。

(i) SQL手続き文

繰り返し実行するSQL手続き文を指定します。

FOR文の中で指定するSQL手続き文の規則
  • FOR文のカーソルを指定したOPEN文,FETCH文,及びCLOSE文は指定できません。

  • ループ変数名を指定したLEAVE文は指定できません。

  • FOR文のカーソルがホールダブルカーソルではない場合,COMMIT文,ROLLBACK文,及びPURGE TABLE文は指定できません。また,CALL文でこれらを指定した手続きが呼び出された場合は実行時エラーとなります。

  • 指定したSQL手続き文は指定した順序で実行されます。SQL手続き文の実行でエラーが発生した場合,それ以降のSQL手続き文は実行されません。FOR文の実行も終了します。

(j) END FOR 〔終了ラベル〕

FOR文の終了を指定します。終了ラベルには,文ラベルを指定します。

(4) 共通規則

  1. 終了ラベルを指定する場合は,開始ラベルと同じ名称の文ラベルを指定してください。

  2. 文ラベル,及びループ変数名の有効範囲は,FOR文の開始から終了までの間です。そのFOR文中に含まれるほかの文の文ラベル,ループ変数名と同じ名称の文ラベル,及びループ変数名は指定できません。ただし,SQL手続き文中にハンドラ宣言がある場合,そのハンドラ宣言中は除きます。

  3. FOR文中で暗黙的に宣言したSQL変数,及び明示的に宣言したカーソルは,そのFOR文の最初に割り当てられ,最後に解放されます。

  4. FOR文で暗黙的に宣言したSQL変数,及び明示的に宣言したカーソルの有効範囲は,そのSQL変数及びカーソルが宣言されているFOR文の中になります。

  5. FOR文の中のSQL手続き文に複合文を指定した場合,及び複合文の中のSQL手続き文にFOR文を指定した場合,FOR文で暗黙的に宣言したSQL変数と,複合文の中で宣言したSQL変数が同じ名称のときは,内側のルーチン制御SQLの中では内側のルーチン制御SQLで宣言したSQL変数が有効となります。内側のルーチン制御SQLが終了したら,外側のルーチン制御SQLで宣言したSQL変数が有効となります。例を次に示します。

    [図データ]

  6. FOR文の中のSQL手続き文にFOR文を指定した場合,外側のFOR文で暗黙的に宣言したSQL変数と内側のFOR文で暗黙的に宣言したSQL変数が同じ名称のときは,内側のFOR文の中では内側のFOR文で宣言したSQL変数が有効となります。内側のFOR文が終了したら,外側のFOR文で宣言したSQL変数が有効となります。

  7. FOR文の中のSQL手続き文に複合文を指定した場合,及び複合文の中のSQL手続き文にFOR文を指定した場合,FOR文で宣言したカーソルと,複合文の中で宣言したカーソルが同じ名称のときは,内側のルーチン制御SQLの中では内側で宣言したカーソルが有効となります。内側のルーチン制御SQLが終了したら,外側で宣言したカーソルが有効となります。

  8. FOR文の中のSQL手続き文にFOR文を指定した場合,外側のFOR文で宣言したカーソルと内側のFOR文で宣言したカーソルが同じ名称のときは,内側のFOR文の中では内側のFOR文で宣言したカーソルが有効となります。内側のFOR文が終了したら,外側のFOR文で宣言したカーソルが有効となります。

  9. SQL手続きの実行中にエラーが発生した場合に,トランザクションが無効になるのは,そのエラーが暗黙的ロールバックありのときだけです。トリガ動作のSQL手続き文の実行中にエラーが発生した場合は,必ず暗黙的ロールバックとなります。

  10. FOR文,及び複合文のネスト数は,最大255です。

(5) 留意事項

  1. FOR文はSQL手続き中,及びトリガ中に指定できます。

(6) 使用例

表T1のデータのうち,列C1(INT型)の値が100以下のデータは表T2に代入し,それ以外は表T3に代入する手続き(PROC1)を定義します。

CREATE PROCEDURE PROC1 ()
FLBL :
FOR LVN AS SELECT C1,C2,C3 FROM T1 DO
 IF C1 <= 100 THEN
  INSERT INTO T2 VALUES(LVN.C1,LVN.C2,LVN.C3) ;
 ELSE
  INSERT INTO T3 VALUES(LVN.C1,LVN.C2,LVN.C3) ;
 END IF ;
END FOR FLBL

上記使用例で示したFOR文と等価なSQLは以下のSQLで実現できます。

CREATE PROCEDURE PROC1 ()
LVN :
BEGIN 
  DECLARE C1,C2,C3 INT ; 
  DECLARE FCN CURSOR FOR SELECT C1,C2,C3 FROM T1 ;
  DECLARE AT_END CHAR(1) DEFAULT 'N' ; 
  OPEN FCN ;
  FLBL :
  WHILE AT_END != 'Y' DO
    FETCH FCN INTO C1,C2,C3 ;
    IF SQLCODE = 100 THEN
      SET AT_END = 'Y' ;
    ELSE
      IF C1 <= 100 THEN
        INSERT INTO T2 VALUES(LVN.C1,LVN.C2,LVN.C3) ;
      ELSE
        INSERT INTO T3 VALUES(LVN.C1,LVN.C2,LVN.C3) ;
      END IF ;
    END IF ;
  END WHILE FLBL ;
 CLOSE FCN ;
END LVN