あるデータベースユーザ(ユーザA)が
ストアド・パッケージ2つ保持しており(pkg1とpkg2)、
pkg1の中でpkg2を呼び出すネスト構造になっております。
別のデータベースユーザ(ユーザB)でこのストアド・パッケージを
利用する要件があり、
ユーザAのpkg1に対してexecute オブジェクト権限をユーザBに付与し、
ユーザBでシノニム参照してpkg1を呼び出す仕組みで運用しておりました。
pkg2についてはpkg1のexecuteオブジェクト権限のみで実行されます。
データベースユーザ(ユーザA)のデイリー処理にて
オブジェクトがINVALIDとなっているものについて
リコンパイルしてVALIDに戻すバッチ処理が稼働しているのですが、
ある日、pkg2のみリコンパイル対象となった場合に
ユーザBからのpkg1実行にてpkg2が空振りして終了する事象が発生しました。
ユーザAからのpkg1実行は問題なくpkg2も稼働して正常終了します。
なおその後pkg1をリコンパイルすると、上記事象は解消され
ユーザBからのpkg1実行も正常終了します。
ネストしたパッケージについては、
子のパッケージ(pkg2)をリコンパイルした場合には
ストアド・パッケージpkg1で内包されていると思われるpkg2に対する
executeオブジェクト権限が外れてしまう等の動作になるのでしょうか。
所有者となっているユーザAではその事象が確認されないので
恐らくそうではないかとは考えてはおります。ご教授いただけると幸いです。
対策としては、
・pkg2がINVALIDになった場合pkg2だけでなくpkg1もリコンパイルする
・pkg1とpkg2をネスト構造にせず1パッケージにまとめる
等を検討しております。
(11/30追記)
その後、INVALIDになる原因と対処については実施済となり
pkg2だけがリコンパイルされる事例は排除したのですが、
上述の、pkg1とpkg2について
pkg1:VALID
pkg2:VALID (こちらを後からコンパイルした)
と両方VALIDになっているにもかかわらず、
別ユーザBからのpkg1実行がpkg2を呼び出せずに終了してしまう、
という動作の要因が良く理解できていないままとなっておりました。
そこで以下のようなサンプルを用いてテストをしていたところ、
(結論はコードが悪いに尽きるのですが…)
子パッケージのほうに未使用の変数(i)がありそれが悪さをしていたようです。
PLSQL
1/* 親パッケージ */ 2create or replace package pkg_oya as 3 type VARARRAY is table of varchar2(2000) index by binary_integer; 4 i binary_integer; 5 procedure spr_oya ( i_cd in number, 6 sts out number); 7End pkg_oya; 8/ 9create or replace package body pkg_oya as 10 procedure spr_oya ( i_cd in number, 11 sts out number) is 12 begin 13 /* 子パッケージ呼出し 子からsts=88を受け取る */ 14 pkg_ko.spr_ko( i_cd, sts ); 15 16 if sts = 88 then 17 sts := 88; 18 else 19 sts := 0; 20 end if; 21 exception 22 when others then 23 sts := 99; 24 end spr_oya; 25End pkg_oya; 26/
PLSQL
1/* 子パッケージ */ 2create or replace package pkg_ko as 3 i BINARY_INTEGER; 4 5 Procedure spr_ko 6 (i_cd in number, 7 sts in out number); 8End pkg_ko; 9/ 10create or replace package body pkg_ko is 11 Procedure spr_ko 12 (i_cd in number, 13 sts in out number) is 14 Begin 15 sts := 88; 16 goto end_proc; 17 18 << abort_proc >> 19 20 << end_proc >> 21 null; 22 End spr_ko; 23End; 24/
確認手順
1.ユーザAで親パッケージ(pkg_oya)、子パッケージ(pkg_ko)を定義
2.ユーザB向けにGRANT EXECUTE(pkg_oyaのみ付与。)
3.ユーザB側でpkg_oyaを実行(例えば以下で実行すれば子パッケージのコード88が返却される)
DECLARE i_cd NUMBER := 1234; o_data NUMBER; BEGIN pkg_oya.spr_oya(i_cd,o_data); DBMS_OUTPUT.PUT_LINE(o_data); END;
4.その後、ユーザAで子パッケージ(pkg_ko)をリコンパイル
5.ユーザB側でpkg_oyaを実行(子パッケージ部でExceptionになりコード99が返却される)
6.ユーザA側でpkg_oyaを実行(子パッケージのコード88が返却される)
7.ユーザAで親パッケージ(pkg_oya)をリコンパイルし、再度ユーザBへ権限設定
8.ユーザB側でpkg_oyaを実行(子パッケージのコード88が返却される)(元に戻る)
なお、該当の変数iを子パッケージから除去すると、
上述の子パッケージをコンパイルしても、上述の5.
の実行結果は子パッケージ呼出し時にExceptionにならず、88が返却されました。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/11/12 02:14
2020/11/12 02:43
2020/11/27 08:26
2020/11/27 10:11
2020/11/30 02:32
2020/11/30 06:40
2020/11/30 11:02
2020/11/30 11:24