ストアドプロシージャのパラメータnocopyについて
http://www.shift-the-oracle.com/plsql/subprogram-parameter-mode.html
上記のサイトをみててORACLEでは参照渡ししているわけではないことを初めて知った。
参照渡しするにはnocopyヒントを付ける必要があるとのこと。
参照渡しならば、メモリ食わなくてすむのでコレクションなどの引き渡し時に
使いたいところですが、例外の時の動きが異なるらしい。
下記のプロシージャを実行すると
CREATE OR REPLACE PROCEDURE NCP_TEST IS NCPNUM NUMBER; CPNUM NUMBER; PROCEDURE NCP(NUM IN OUT NOCOPY NUMBER) IS BEGIN NUM := 100; RAISE VALUE_ERROR; END; PROCEDURE CP(NUM IN OUT NUMBER) IS BEGIN NUM := 100; RAISE VALUE_ERROR; END; BEGIN NCPNUM := 1; CPNUM := 1; BEGIN NCP(NCPNUM); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(NCPNUM); END; BEGIN CP(CPNUM); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(CPNUM); END; END; /
例外発生時にCPの方はCPNUMが1だが、NCPの方はNCPNUMは100になる。
NOCOPYヒントを付けてると、代入した時点で参照ポインタの値を直接書き換えるため
例外が発生しても値は書き換わっている。
逆にNOCOPYヒントを付けない場合は、呼び出したプロシージャ内での処理が完了したあとに
パラメータを書き換えるので処理中に例外が発生した場合には呼び出し元の
変数内容は書き換わらない。
バグの原因になりそうな気がするのでNOCOPYヒント使うときは例外処理に
注意してコーディングする必要がありますね。