DB/Oracle/PLSQL/カーソル
目次†
カーソル!
カーソルの種類†
カーソルっていうのは、メモリ領域に対するポインタ。より具体的には、SQL 文を実行したときの結果セットに対する、現在の処理対象である行へのポインタのこと。明示カーソルと暗黙カーソルがある。表をごにょごにょするときに、今どの行を見ているかとか、そういう情報を内部的に持っているような感じ。
暗黙カーソルと明示カーソルがある。
- カーソルの種類
種類 説明 暗黙カーソル DML や SELECT 文の実行時に、PL/SQL さんが勝手に作るカーソル 明示カーソル プログラムを書くときときにきちんと宣言してきちんと使うためのカーソル。主に SELECT 文の結果が複数行になるときに使う
暗黙カーソル†
DML や SELECT 文の発行時、PL/SQL によって勝手に作られて使われて破棄されるカーソル。必要に応じて勝手に生成、操作されるので、動きは意識する必要はない。
ただ、直前の SQL 文の実行結果に関する情報を SQL カーソル属性としてもつので、これは活用できる。これを参照することで、直前の SQL 文がどのように処理されたかがわかる。
カーソルの属性†
- SQL カーソル属性の種類
属性 説明 SQL%FOUND ブール型。直前の SQL 文で 1 行以上返ってきた場合に TRUE SQL%NOTFOUND ブール型。直前の SQL 文で 1 行も返ってこなかった場合に TRUE SQL%ROWCOUNT 整数型。直前の SQL 文で影響を受けた行数
- SQL カーソル属性
begin update set ... -- 直前の SQL 文(この場合 UPDATE)で何行更新されたか表示 dbms_output.put_line(sql%rowcount); ...
明示カーソル†
プログラマが明示的に生成して操作する、結果セットに対するポインタ。
通常、SQL では行単位でしか操作できないので、複数行を戻す問い合わせを処理する場合などには明示的に処理対象とする行を指定しないといけない。
ざっくりとした使い方は以下。
- カーソルの宣言
- CORSOR hoge IS SELECT ...;
- カーソルのオープン
- OPEN hoge;
- カーソルに関連付けられた SQL 文を実行
- カーソルを結果セットの一行目へセット
- OPEN hoge;
- フェッチ
- FETCH hoge INTO fuga;
- カーソルのある行のデータを変数へ格納
- カーソルを次の行へ移動
- FETCH hoge INTO fuga;
- カーソルのクローズ
- CLOSE hoge;
- カーソルと結果セットの解放
- CLOSE hoge;
基本的な書き方†
カーソルの宣言で、任意の SELECT 文をカーソルと関連付け指定できる。ただし変数格納用の INTO は含めない。必要に応じて ORDER BY 句でソートする(結果セットのソートはできないうえ、カーソルは逐次移動しかできないため)。
- 明示カーソル
declare -- カーソルの宣言に実行したい SQL 文を含める cursor c_hoge is select foo, bar, baz from fuga; -- 格納する用の変数を用意しておく v_foo fuga.foo%type; v_bar fuga.bar%type; v_baz fuga.baz%type; -- カーソルの結果に合わせたレコード変数の宣言も可能 v_record c_hoge%rowtype; begin -- カーソルのオープン open c_hoge; -- 検索結果すべてに対してのループ処理 loop -- カーソルのある行のデータを変数に格納する fetch c_hoge into v_foo, v_bar, v_baz; -- 行がなければループを終了する exit when c_hoge%notfound; -- 行があった場合の処理を書く ... end loop; end; /
パラメータの付加†
カーソルにパラメータを付加して、オープンするときに値を渡せる。オープン時に渡すパラメータを変えることで、実行する SQL 文中の値を動的に変更できる。
WHERE 句に与える値などをオープンするたびに動的に変更できるので、同じカーソルを再利用できて効率も良い。
- パラメータの付加
declare -- カーソル宣言時にパラメータも記述する cursor c_hoge (p_hoge number, p_fuga varchar2) is select * from foo -- SQL 文中にパラメータを埋め込んでおく where bar = p_hoge and baz = p_fuga; begin -- オープン時に引数っぽく値を渡す -- この例でいえば "where bar = 100 and baz = 'Hoge'" として実行される open c_hoge (100, 'Hoge'); -- クローズして再オープンすればまた違う値を渡せる -- 今度は "where bar = 101 and baz = 'Fuga'" として実行される close c_hoge; open c_hoge (101, 'Fuga'); end; /
カーソルの属性†
暗黙カーソルにもあった属性に、ISOPEN が追加されている。
%NOTFOUND と %ROWCOUNT をよく使う。%ISOPEN はカーソルの再オープン前の状態チェックなどに使用する。こともあるかもしれない。
- 明示カーソル属性の種類
属性 説明 %ISOPEN ブール型。カーソルがオープンしていれば TRUE %FOUND ブール型。最新のフェッチで 1 行以上返ってきた場合に TRUE %NOTFOUND ブール型。最新のフェッチで 1 行も返ってこなかった場合に TRUE %ROWCOUNT 整数型。これまでにフェッチで戻ってきた行の合計数
- 明示カーソル属性
begin ... loop ... -- 上から 10 件だけ処理したいときの例 -- OR 条件は結果が 10 件未満だったときのためのもの exit c_hoge%rowcount > 10 or c_hoge%notfound; ... end loop; ... end;
カーソル FOR ループ†
検索結果に対する FOR EACH みたいなもの。便利。
オープン、フェッチ、終了、クローズは暗黙的に処理されるので記述不要。
- カーソル FOR ループ
declare -- カーソルの宣言は必要 cursor c_hoge is select ...; begin -- レコード変数名を直接指定。宣言不要 for r_hoge in c_hoge loop ... end loop; end; /
副問い合わせを利用すれば、カーソル宣言すら省略できる。コードの可読性が落ちるのと、カーソル属性が使えなくなる点は注意。
- 副問い合わせを利用したカーソル FOR ループ
declare -- カーソルの宣言は不要 begin -- レコード変数名を直接指定。宣言不要 for r_hoge in (select ...) loop ... end loop; end; /
Last-modified: 2011-11-08 (火) 16:59:58