- PR -

PL/SQL例外処理がが行われた後の戻り値の取得

1
投稿者投稿内容
marlboro
会議室デビュー日: 2006/05/12
投稿数: 16
投稿日時: 2006-08-03 17:35
オラクル8.0.4.10
PL/SQLのプロシージャーで、
正常時:戻り値v_outに 0 を返す。
異常時:戻り値v_outに 255 を返す。

をしたいのですが、下記のソースだと、正常時には値'0'が返ってくるのですが、
異常時は、NULLが帰ってきます。

例外処理部から値は戻ってこないのでしょうか?

CREATE OR REPLACE PROCEDURE test(v_in IN number,v_out OUT varchar2)
IS
/* 処理部 *******************************************************************/
BEGIN
v_out := '0';
/* 例外部 *******************************************************************/
EXCEPTION
WHEN OTHERS THEN
v_out := 255;
END;
/
今川 美保(夏椰)
ぬし
会議室デビュー日: 2004/06/10
投稿数: 363
お住まい・勤務地: 神奈川県茅ヶ崎市
投稿日時: 2006-08-03 22:47
試して見ました。
ただ、Oracle8を持っていないので、
Oracle10gExpressにてですが。

コード:
CREATE OR REPLACE PROCEDURE test(v_in IN number,v_out OUT varchar2)
IS
BEGIN
v_out := '0';

v_out := to_char(1 / v_in) ;
dbms_output.put_line('A') ;

EXCEPTION
 WHEN OTHERS THEN
	v_out := '255';
	dbms_output.put_line('B') ;
END ;
/



このプロシージャを作成し、以下のように実行してみました。

まず正常パターン
コード:
SQL> declare
  2   v_in number;
  3   v_out varchar2(10) ;
  4  begin
  5
  6   v_in := 1 ;
  7   test(v_in, v_out) ;
  8
  9   dbms_output.put_line(v_out) ;
 10  end;
 11  /
A
1


v_in = 1 なので、v_out = 1でOK。
プロシージャ内のDBMS_OUTPUT.PUT_LINEにて「A」が出力されているので、
正常パターンで動作している。


次に例外パターン
#0除算エラーを発生させています。
コード:
SQL> declare
  2   v_in number;
  3   v_out varchar2(10) ;
  4  begin
  5
  6   v_in := 0 ;
  7   test(v_in, v_out) ;
  8
  9   dbms_output.put_line(v_out) ;
 10  end;
 11  /
B
255


例外処理へとび、「B」が出力され、戻り値も255になっていることが確認できる。
よって、例外処理からもちゃんと戻り値が返せているといえます。

同じバージョンのOracleを使用していないので、正確ではないですが、
例外時にDBMS_OUTPUT.PUT_LINEを使用してデバッグログを入れてみたりして、
そのロジックが通っているかなど確認してみてはいかがでしょう?
#SQL*Plusなどで実行する際は set aserverout onにしておけば
#プロシージャ内の出力内容もみれますし。
_________________
夏椰 @ わんくま同盟
夏椰の庵
Microsoft MVP for Windows Server System - SQL Server ( Jul 2006 - Jun 2008 )
marlboro
会議室デビュー日: 2006/05/12
投稿数: 16
投稿日時: 2006-08-04 09:56
夏椰さん

丁寧な解説どうもありがとうございます。
Oracle8でも夏椰さんのコードは期待通りの動きをしてくれました。

ただ、当方の本番用プロシージャーで試したとこ、やはりテストでいうところの
v_out = 255 が返ってこず、NULLの状態でした。

EXCEPTION
WHEN OTHERS THEN
v_out := '255';
dbms_output.put_line(v_out);
raise_application_error(-20000,'EXCEPTION');

ObjectBrowser8.0でデバックしていっても、変数v_outにはしっかり255という値が入っているのに、処理が終わると、NULLになってしまっています。
そこで、最後の行raise_application_errorを削除したところ、
きっちり255が返ってきました!!
これが原因だということが分かったのですが、仕様上この行ははずせなさそうです。
raise_application_errorを使いながら例外部での変数は戻り値として返すことができないのでしょうか?

試しに夏椰さんのテストソースにraise_application_errorを入れてみました。


CREATE OR REPLACE PROCEDURE test(v_in IN number,v_out OUT varchar2)
IS
BEGIN
v_out := '0';

v_out := to_char(1 / v_in) ;
dbms_output.put_line('A') ;

EXCEPTION
WHEN OTHERS THEN
v_out := '255';
dbms_output.put_line('B') ;
raise_application_error(-20000,v_out); ←ここ
END ;


そして、SQL*Plusから
declare
v_in number;
v_out varchar2(10) ;
begin
v_in := 0 ;
test(v_in, v_out) ;
dbms_output.put_line(v_out) ;
end;
/

***結果***
B
declare
*
行1でエラーが発生しました。:
ORA-20000: 255
ORA-06512: "AAU.TEST", 行13
ORA-06512: 行6


1

スキルアップ/キャリアアップ(JOB@IT)