使用名称的字符串表示来调用PLSQL存储过程

时间:2017-02-08 15:20:27

标签: oracle plsql

我有一个以给定顺序为表中的所有行调用的过程列表。我想将它们全部添加到一个单独的表中,而不是硬编码过程调用,并遍历包含调用每个过程的过程的行。所有过程都需要相同的输入参数。

这一切都可能吗?

3 个答案:

答案 0 :(得分: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)

答案 1 :(得分: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;

执行所有程序。

答案 2 :(得分:1)

在这个例子中可能有些过分,但是对于这种事情,你可以将execute immediate封装在一个类型定义中,这样循环就可以执行类似r.task.run();的东西

定义一项任务'类型:

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 );

一些演示程序:

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

在这个例子中,它可能不会给你带来太大的影响,但作为一种方法,它值得记住。