先ほどの説明からも分かる通り、カーソル処理の記述はこれまでの連載内容と比べると複雑です。まずは、図5でカーソルを使う際に必要な記述の全体像を確認してください。
それでは、図5をベースに各項目の記述方法を解説します。
実行したいSELECT文に対してカーソル名を定義します。カーソル名は変数と同様の「命名規則」に従います。このとき「SQL」という名前は指定できません。
CURSOR <カーソル名> IS <問い合わせ文> ;
実行部でカーソルの結果セットを1行ずつ変数に代入します。変数はカーソルの結果セットの列ごとに定義するのではなく、通常は「<カーソル名>%ROWTYPE」と定義します。こうすることで、結果セットと同じ行構造の変数を用意できます。
<変数名> <カーソル名>%ROWTYPE ;
カーソルに対応付けられたSELECT文を実行し、結果セットを識別します。結果セットはオープンした時点のデータを保持します。
OPEN <カーソル名> ;
カーソルの結果セットから1行を取り出し、(2)で定義した変数に代入します。
FETCH <カーソル名> INTO <変数名> ;
FETCH INTO文を使用する際は、次に挙げる挙動に注意してください。
LOOP処理によって結果セットから複数行を取り出した後、このLOOP処理を終了する条件が必要です。終了条件の指定方法は幾つかありますが、今回はEXIT WHEN文を使用した方法を解説します。
EXIT WHEN <終了条件> ;
終了条件にはWHERE句と同様の条件式を指定できる他、後ほど説明する「カーソル属性」を指定できます。カーソル属性を使用すると、例えば「結果セットの全行を取り出して、取り出す行がなくなったらLOOP処理を終了する」というような指定が可能です。
結果セットが確保していたメモリ領域を解放します。なお、クローズ処理の明示的な指定を省略できますが、その場合、PL/SQLブロックが終了するまでは結果セットのメモリ領域を確保し続けます。メモリを有効活用するためにも、一連の処理が終了したらクローズ処理を指定するようにしましょう。
CLOSE <カーソル名> ;
それでは、カーソルの記述方法をサンプルプログラムで確認しましょう。
SQL> DECLARE 2 CURSOR dept_cur IS SELECT * FROM dept; 3 dept_rec dept_cur%ROWTYPE; 4 BEGIN 5 OPEN dept_cur; 6 LOOP 7 FETCH dept_cur INTO dept_rec; 8 EXIT WHEN dept_cur%NOTFOUND; 9 DBMS_OUTPUT.PUT_LINE(dept_rec.deptno||' : '||dept_rec.dname||' : '||dept_rec.loc); 10 END LOOP; 11 CLOSE dept_cur; 12 END; 13 / 10 : ACCOUNTING : NEW YORK 20 : RESEARCH : DALLAS 30 : SALES : CHICAGO 40 : OPERATIONS : BOSTON
初めに宣言部で「SELECT * FROM dept;」というSELECT文に対して、DEPT_CURという名前でカーソル名を定義しています。併せて、カーソルの結果セットの行を代入するため、変数DEPT_RECを「dept_cur%ROWTYPE」で定義しています。
次に実行部でOPEN文を使用し、カーソルDEPT_CURに対応付けたSELECT文を実行しています。これによって結果セットが識別されます。その後、FETCH INTO文を使用して、結果セットの1行目を変数DEPT_RECに代入しています。そして、変数DEPT_RECの各フィールドに代入されている値をDBMS_OUTPUT.PUT_LINEで出力しています。
この「変数への代入→値の出力」という一連の処理を、結果セットの2行目以降でも繰り返し行うため、LOOP文を併用しています。また、LOOP〜END LOOP間には、LOOP処理を終了するためにEXIT WHEN文を指定しています。「dept_cur%NOTFOUND」という条件を指定しているため、カーソルDEPT_CURの結果セットが全行取り出され、取り出す行がなくなったらLOOP処理を終了します(カーソル属性の%NOTFOUNDは次に説明します)。
最後にCLOSE文を指定し、カーソルをクローズしています。これで結果セットが確保していたメモリ領域を解放します。
Copyright © ITmedia, Inc. All Rights Reserved.