SAK 図書館
Oracle PL/SQL 編5 - カーソル、カーソル for ループ、例外識別子、例外処理
■カーソル操作 (フェッチ、カーソル移動)
set serveroutput on;
declare
jcrec 受注m%rowtype;
cursor cu is select * from 受注m where 品番 = 'a001';
begin
open cu;
loop
fetch cu into jcrec;
exit when cu%notfound;
dbms_output.put_line (jcrec.受注番号);
end loop;
close cu;
end;
/
■カーソル変数操作 (フェッチ、カーソル移動)
set serveroutput on;
declare
type tpjcrec is ref cursor return 受注m%rowtype;
--type tpjcrec is ref cursor; /* 制限的でない弱い型 */
cv tpjcrec;
jcrec 受注m%rowtype;
begin
open cv for select * from 受注m where 品番 = 'a001';
loop
fetch cv into jcrec;
exit when cv%notfound;
dbms_output.put_line (jcrec.受注番号);
end loop;
close cv;
end;
/
■カーソル for ループ (カーソルループ、カーソル移動)
set serveroutput on;
declare
cursor cu is select * from 受注m where 品番 = 'a001';
begin
for cu_rec in cu loop
dbms_output.put_line (cu_rec.受注番号);
end loop;
end;
/
■カーソル for ループ (副問い合わせ、副問合わせ)
set serveroutput on;
declare
begin
for cu_rec in (select * from 受注m) loop
dbms_output.put_line (cu_rec.受注番号);
end loop;
end;
/
■レコードグルーブシーケンス番号を付与して、CSV 形式で問い合わせ
set serveroutput on;
declare
cursor c1 is select 得意先CD, 品番
from 受注m order by 得意先CD, 品番;
ct number;
svtkcd varchar2(20) := ' ';
begin
dbms_output.put_line ('start...');
for rec in c1 loop
if svtkcd != rec.得意先CD then
ct := 0;
svtkcd := rec.得意先CD;
end if;
ct := ct + 1;
dbms_output.put_line (
'"' || ct || '","'
|| rec.得意先CD || '","'
|| rec.品番 || '"'
);
end loop;
dbms_output.put_line ('end');
exception
when OTHERS then
dbms_output.put_line ('** エラー **');
end;
/
start...
"1","1000","a001"
"2","1000","b002"
"3","1000","c003"
"1","2000","a001"
"2","2000","b002"
end
■カーソル属性
カーソル%found fetch が行を戻せば TRUE
カーソル%isopen オープンされていれば TRUE
カーソル%notfound fetch が行を戻さなければ TRUE
カーソル%rowcount fetch された行数
■暗黙カーソル属性
sql%found insert、update、delete が 1 行以上処理すれば TRUE
sql%isopen 常に FALSE
sql%notfound insert、update、delete が処理対象なしの場合、TRUE
sql%rowcount insert、update、delete が処理したレコード数
sql%%bulk_rowcount forall での処理レコード数
** 暗黙カーソル属性は、レコード追加件数、レコード修正件数、
レコード削除件数など、レコード更新件数取得に使用可能です。
■テーブルロック
lock table 受注m in row share mode nowait; 行共有モード
■例外識別子
ACCESS_INTO_NULL 未初期化オブジェクトに代入した ORA-06530
COLLECTION_IS_NULL コレクション未初期化 ORA-06531
CURSOR_ALREADY_OPEN カーソルが既にオープンされている ORA-06511
DUP_VAL_ON_INDEX キーが重複した ORA-00001
INVALID_CURSOR カーソルがオープンされていない ORA-01001
INVALID_NUMBER 数値が正しくない ORA-01722
LOGIN_DENIED ログインできない ORA-01017
NO_DATA_FOUND SELECT INTO レコードなし ORA-01403
NOT_LOGGED_ON ログインできていない ORA-01012
PROGRAM_ERROR PL/SQL 内部エラー ORA-06501
ROWTYPE_MISMATCH 互換性なし ORA-06504
STORAGE_ERROR PL/SQL メモリ不足 ORA-06500
SUBSCRIPT_BEYOND_COUNT コネクション要素オーバ ORA-06533
SUBSCRIPT_OUTSIDE_LIMIT 有効範囲外添字 ORA-06532
TIMEOUT_ON_RESOURCE タイムアウト ORA-00051
TOO_MANY_ROWS 複数行あり ORA-01422
VALUE_ERROR 算術エラー ORA-06502
ZERO_DIVIDE ゼロの割り算 ORA-01476
・SQLCODE としては、ORA-06511 の値がマイナスで返る。
ORA-06511 なら、-6511。
但し、ORA-01403 は、SQLCODE として、+100 が返るので注意する。
・SQLERRM では、SQLCODE に対応するエラーメッセージを取得できる。
errmsg := sqlerrm(-6511);
■例外処理(EXCEPTION)
・others で、なにかエラーがあれば、rollback する。
declare
jcsu number(12, 2);
begin
jcsu := 100;
insert into 受注m values ('111111-011', 'a001', jcsu, '1000',
'sak', '2001.08.25', '07:02:00');
insert into 受注m values ('111111-011', 'a001', jcsu, '1000',
'sak', '2001.08.25', '07:02:00');
commit;
exception
when others then
rollback;
end;
/
・特定のエラーと、その他エラーで対処が異なる場合は、次のようにする。
declare
jcsu number(12, 2);
begin
jcsu := 100;
insert into 受注m values ('111111-011', 'a001', jcsu, '1000',
'sak', '2001.08.25', '07:02:00');
insert into 受注m values ('111111-011', 'a001', jcsu, '1000',
'sak', '2001.08.25', '07:02:00');
commit;
exception
when dup_val_on_index then
...
...
rollback;
when others then
rollback;
end;
/
・正常、エラーにかかわらず、共通の処理がある場合は、次のようにする。
declare
jcsu number(12, 2);
begin
...
...
begin
jcsu := 100;
insert into 受注m values ('111111-011', 'a001', jcsu, '1000',
'sak', '2001.08.25', '07:02:00');
insert into 受注m values ('111111-011', 'a001', jcsu, '1000',
'sak', '2001.08.25', '07:02:00');
commit;
exception
when dup_val_on_index then
...
...
rollback;
when others then
rollback;
end;
...
...
end;
/
■例外呼び出し(RAISE、RAISE_APPLICATION_ERROR)
・ユーザ例外を定義し利用するには、次のようにする。
declare
USER_ERR_TEST exception;
begin
...
if ... then
raise USER_ERR_TEST;
end if;
...
exception
when USER_ERR_TEST then
...
when others then
...
end;
/
・ユーザ例外エラーを呼び出しもとに返すには、次のようにする。
呼び出しもとは、pragma exception_init(err_call, -20001); を使用して、
exception when err_call then... のように処理することができる。
declare
...
begin
...
if ... then
raise_application_error(-20001, 'ストアドエラー');
end if;
...
end;
/
■Oracle PL/SQL 編資料
■SQL 基礎実地編資料
■SQL 基礎編資料
■SQL チューニング編資料
■PostgreSQL 編、JAVA Servlet、JSP 編資料
■MySQL 編資料