我想在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语句(使用一个或多个输入和输出变量立即执行)但始终使用相同的前后模式方法。
有人知道如何解决这个问题吗?
答案 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。您可以再次使用正确的数据类型覆盖该过程 - 请注意,这可能会使多种数据类型或参数数量变得混乱。