2017-02-08 11 views
2

テーブル内のすべての行に対して、指定された順序で呼び出されるプロシージャのリストがあります。プロシージャ呼び出しをハードコーディングするのではなく、それらをすべて別のテーブルに追加し、それぞれを呼び出すプロシージャを含む行をループしたいと思います。すべての手順には同じ入力パラメータが必要です。名前の文字列表現を使用してPLSQLストアドプロシージャを呼び出す

これはすべて可能ですか?

答えて

5

は、あなたがこのテーブルを持っていると言う:

create table procs(procName) as (
    select 'proc1' from dual union all 
    select 'proc2' from dual union all 
    select 'proc3' from dual 
)  

とこれらの手順:

create or replace procedure proc1(p1 in varchar2, p2 in number) is begin dbms_output.put_line('running Proc1(' || p1 || ', ' || p2 || ')'); end; 
create or replace procedure proc2(p1 in varchar2, p2 in number) is begin dbms_output.put_line('running Proc2(' || p1 || ', ' || p2 || ')'); end; 
create or replace procedure proc3(p1 in varchar2, p2 in number) is begin dbms_output.put_line('running Proc3(' || p1 || ', ' || p2 || ')'); end; 

あなたが試すことがあります。あなたは何を得る

declare 
    yourParameter1 varchar2(10) := 'X'; 
    yourParameter2 number  := 10; 
begin 
    for i in (select procName from procs order by procName) loop 
     execute immediate 'begin ' || i.procName || '(:1, :2); end;' using yourParameter1, yourParameter2; 
    end loop; 
end; 

running Proc1(X, 10) 
running Proc2(X, 10) 
running Proc3(X, 10) 
+0

素敵な、多くのありがとう! – bjelleklang

2

テーブルprocedures_to_runがあり、実行するプロシージャの名前をカラムnameが処理し、その順序を決定するidがあるとします。

begin 
for x in (select name from procedures_to_run order by id) loop 
    execute immediate 'call '|| x.name ||'(INPUT_PARAMS)'; 
end loop; 
end; 

すべての手順を実行することができます。

+0

申し訳ありませんが、それはdownvoted取得答えが間違っている? – Kacper

+0

バインド変数 –

+0

を使用していないという著者は、すべてのプロシージャに同じパラメータが必要であるため、ハードコーディングしても問題にはならないと述べています。しかし、はい、私はバインド変数がここでコードを良くすることに同意します。ありがとう。 – Kacper

1

それは、この例ではやり過ぎおそらくだが、ループは単に「タスク」タイプを定義

r.task.run();ような何かを実行できるように、この種のもののためにあなたは、タイプ定義内 execute immediateをカプセル化することができます:

create or replace type task as object 
(command varchar2(100) 
, member procedure run); 
/

create or replace type body task 
as 
    member procedure run 
    is 
    begin 
     execute immediate 'begin ' || self.command || '; end;'; 
    exception 
     when others then 
      raise_application_error(-20000, 'Command failed: ' || self.command, true); 
    end run; 
end; 
/

今、あなたのテーブルではなく、プレーンな文字列の「タスク」の列を持つことができます。

create table demo_tasks 
(created_tate date default sysdate not null 
, last_run_date date 
, succeeded_yn varchar2(1) check (succeeded_yn in ('Y','N')) 
, task   task not null); 

いくつかのデモの手順:

それぞれを実行する保存されたタスク210〜
create or replace procedure p1 as begin dbms_output.put_line('This is ' || $$plsql_unit); end; 
/
create or replace procedure p2 as begin dbms_output.put_line('This is ' || $$plsql_unit); end; 
/
create or replace procedure p3 as begin dbms_output.put_line('This is ' || $$plsql_unit); end; 
/

insert into demo_tasks (task) values (task('p1')); 
insert into demo_tasks (task) values (task('p2')); 
insert into demo_tasks (task) values (task('p3')); 

ループ:

begin 
    for r in (
     select * from demo_tasks 
    ) 
    loop 
     -- Add code here to update run date, status etc 
     r.task.run(); 
    end loop; 
end; 
/

This is P1 
This is P2 
This is P3 

これは、この例ではあなたに多くを購入しないかもしれないが、それはアプローチとして念頭に値します。

関連する問題