2015年11月17日火曜日

PLSQL カーソルを使用してデータを取得する

以前に「PLSQL SELECTの結果を取得する~取得結果が複数行の場合~ 」でカーソルの使い方についてまとめました。

以下はその時に使用したコードで、カーソルを使用して、データを取得しています。
DECLARE
    --カーソル定義
    CURSOR member_csr IS 
        SELECT * FROM Member;
    --変数宣言
    memberid VARCHAR2(4);
    membername VARCHAR2(10);
    rank VARCHAR2(2);
BEGIN
    --カーソルオープン
    OPEN member_csr;
    
    LOOP
      --カーソルから1件データを取り出し、変数に代入
      FETCH member_csr INTO memberid, membername, rank;
      --カーソルにデータがなければ、ループ終了
      EXIT WHEN member_csr%NOTFOUND;
      --出力
      SYS.DBMS_OUTPUT.PUT_LINE(memberid || ' ' || membername || ' ' || rank);    
    END LOOP;
    
    --カーソルクローズ
    CLOSE member_csr;
END;
しかし、このコードではカーソルを開いてから例外が発生すると、カーソルが閉じられません。
そこで「PLSQL 例外処理のネスト 」でまとめたように、例外が発生してもカーソルが確実に閉じられるようにします。
DECLARE
    --カーソル定義
    CURSOR member_csr IS 
        SELECT * FROM Member;
    --変数宣言
    memberid VARCHAR2(4);
    membername VARCHAR2(10);
    rank VARCHAR2(2);
BEGIN
    --カーソルオープン
    OPEN member_csr;
    
    BEGIN

        LOOP
          --カーソルから1件データを取り出し、変数に代入
          FETCH member_csr INTO memberid, membername, rank;
          --カーソルにデータがなければ、ループ終了
          EXIT WHEN member_csr%NOTFOUND;
          --出力
          SYS.DBMS_OUTPUT.PUT_LINE(memberid || ' ' || membername || ' ' || rank);    
        END LOOP;
        
        --カーソルクローズ
        CLOSE member_csr;

    EXCEPTION
        WHEN others THEN
            --例外が発生してもカーソルをクローズする
            CLOSE member_csr;
            --例外を親ブロックへ伝播する。(必要な場合のみ)
            RAISE;
    END;

END;

カーソルFORループ


カーソルFORループを使用すると、カーソルを使用してデータを取得する際の以下の処理が省略できます。
  • カーソルのデータを格納する変数を宣言する。
  • カーソルをオープンする。
  • フェッチで1行分のデータを取り出す。
  • カーソルを閉じる。
カーソルが自動で閉じられるので、例外発生時にカーソルが確実に閉じられるよう考慮する必要もありません。

カーソルFORループは以下のように定義します。
FOR レコード変数 IN カーソル LOOP
    処理
END LOOP;

カーソルFORループを使用して、データを取得するコードです。
DECLARE
    --カーソル定義
    CURSOR member_csr IS 
        SELECT * FROM Member;
   
BEGIN

    FOR member_rec IN member_csr LOOP
        SYS.DBMS_OUTPUT.PUT_LINE(member_rec.memberid || ' ' || member_rec.membername);    
    END LOOP;
   
END;

0 件のコメント: