PL / SQL Before-After-Pattern

时间:2012-01-09 10:11:57

标签: oracle plsql

我想在PL / SQL(PSEUDO CODE)中使用前后模式方法:

模式方法:

procedure doIt(DO_SOMETHING)
is
  l_cnt                     pls_integer := 1;
begin
   loop
      begin
        DO_SOMETHING;
        exit;

      exception
        when exception changed then
          if l_cnt = 2 then
            --raise exception...
          else
            l_cnt := l_cnt + 1;
          end if;
       end;
    end loop;
end;  

执行它:

begin
  doIt(execute immediate sql_statement using in or out);
end;

正如您所看到的,我想使用不同的动态sql语句(使用一个或多个输入和输出变量立即执行)但始终使用相同的前后模式方法。

有人知道如何解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

这个解决方案不是很好,但它确实有效。也许你可以从它开始并做出更好的事情:
我在doIt函数中使用了2个参数 -
1)立即执行的命令
2)作为anydata类型的参数
在执行立即执行命令中,我将所有逻辑从将数据转换为我创建的某种类型来包装IN OUT参数。

这是代码:

应该为每个不同的命令创建这样的类型:

create or replace type some_type as object(a number, b number);
/

这是程序:

create or replace procedure doIt(aa in varchar2, param IN OUT anydata) is
begin
  execute immediate aa using in out param;
end doIt;
/ 

这就是我称呼它的方式(在这个例子中我只是从双重选择了count(*)到一些OUT参数):

declare
  i number;
  prm some_type;
  ad anydata;
  a number;
  b number;
begin

  prm := new some_type(a,b);
  ad := anydata.convertobject(prm);

  doIt('declare prmAd anydata := :0; prm1 some_type; x number; begin x := prmAd.getobject(prm1); select count(*) into prm1.a from dual; :0 := anydata.convertobject(prm1); end;', ad);

  i := ad.GetObject(prm);
  dbms_output.put_line(prm.a);
end;

基本上你可以根据需要添加到doIt过程,并使用任何命令运行它。

我猜你可以把事情搞砸 - 将一些执行立即字符串移动到doIt程序,也许更好地声明类型等等。

答案 1 :(得分:0)

我找不到很多关于之前/之后模式的信息,但看看你想要达到的目标看起来像这样:

create or replace
procedure doIt(stmt in varchar2, param in varchar2)
is
  l_cnt pls_integer := 1;
begin
   loop
      begin
        execute immediate stmt using param;
        exit;

      exception
        when others then
          if l_cnt = 2 then
            raise;
          else
            l_cnt := l_cnt + 1;
          end if;
       end;
    end loop;
end;  
/

-- run it 
exec doIt('insert into my_table (col1) values ( :val1 )', 'richard' );

这里的问题是,如果你想传递两个参数,那么你将不得不覆盖'doIt',例如:

procedure doIt(stmt in varchar2, param1 in varchar2, param2 in varchar2)
... 
using param1, param2

另一个警告是将不同的数据类型传递给param。您可以再次使用正确的数据类型覆盖该过程 - 请注意,这可能会使多种数据类型或参数数量变得混乱。