您好我正在编写一个程序调用的程序,此程序将进一步调用另一个程序来执行不同的业务逻辑。所以我做了这样的事。
PROCEDURE calculator(service_id IN NUMBER, amount IN NUMBER) as
p_proc_name varchar(100);
begin
select sc.procedure_name into p_proc_name from test.procedure sc where sc.service_config_id = service_id;
begin
execute immediate (p_proc_name) using 1;
exception when NO_DATA_FOUND then
DBMS_OUTPUT.PUT_LINE('p_proc_name = ' || p_proc_name);
end;
end sb_referal_calculator;
PROCEDURE f_service(amount IN NUMBER) as
cmpany_id NUMBER;
service_date date;
leases_days NUMBER;
referal_amount Number;
requested_quote_id number :=1;
begin
referal_amount :=0;
DBMS_OUTPUT.PUT_LINE('service_date = ');
end f_service;
PROCEDURE d_service(amount IN NUMBER) as
cmpany_id NUMBER;
service_date date;
leases_days NUMBER;
referal_amount Number;
requested_quote_id number :=1;
begin
referal_amount :=0;
DBMS_OUTPUT.PUT_LINE('service_date = ');
end d_service;
所以这里的calcultor程序会动态找到另一个程序名,并尝试用参数执行它。但它给出了一个错误。 这只是一个测试程序。
Executing PL/SQL: CALL DBMS_DEBUG_JDWP.CONNECT_TCP( '10.1.26.70', '55891' )
Debugger accepted connection from database on port 55891.
ORA-00900: invalid SQL statement
ORA-06512: at "test.demo_pkg", line 38
ORA-06512: at line 8
Executing PL/SQL: CALL DBMS_DEBUG_JDWP.DISCONNECT()
Process exited.
我真的不知道这个程序将如何执行此任务。我记得它正在运行,我正在进行测试。但真的不是我所做的并停止工作。
请纠正我的错误。
由于
答案 0 :(得分:1)
使用execute immediate
时,它会在无法查看PL / SQL上下文的SQL上下文中运行动态语句。这有几个影响。首先,您必须从PL / SQL调用您的过程,因此您需要创建一个匿名块,正如Egor Skriptunoff所说,并且您需要的格式完全取决于表(以及您的可变)包含的内容。最短的可能是:
execute immdiate 'begin ' || p_proc_name || ' end;' using 1;
但是假设varible包含如下值:
test_pkg.d_service(:arg);
如果只包含没有参数且没有包限定符的过程的名称,即只有d_service
,它可能需要尽可能多:
execute immdiate 'begin test_pkg.' || p_proc_name || '(:arg); end;' using 1;
或介于两者之间。
另一个影响是过程名称必须是公共的,因为当它被动态调用时,它实际上是从包外部调用的;所以它必须在包规范中声明。根据程序出现在正文中的顺序,这可能就是这种情况。
但是如果你总是在同一个包中调用过程,并且因为你必须拥有有限数量的可能值,那么避免使用动态SQL并使用该值决定调用哪个过程可能更简单:
case p_proc_name
when 'f_service' then
f_service(1);
when 'd_service' then
d_service(1);
-- etc.
end case;
这也让你可以调用私人程序。