我正在尝试编写一个运行单个任意过程的sql * plus脚本。棘手的部分是我希望能够运行该过程,无论该过程有多少参数。
要找出该过程的正确参数数量,我正在执行以下操作:
SELECT COUNT(*) INTO v_in
FROM all_arguments
WHERE LOWER(owner) = LOWER(v_schema)
AND LOWER(package_name) = LOWER(v_package)
AND LOWER(object_name) = LOWER(v_proc)
AND in_out = 'IN';
当构建execute-immediate字符串时,我想使用某种循环来做到这一点。所有传入的参数都只是编号,& 1到& n。
FOR i IN 1..v_in
LOOP
v_block := v_block || '''' || &i || '''';
IF i != v_in THEN
v_block := v_block || ',';
END IF;
END LOOP;
然而,这不起作用。它看到& i当然认为它是一个名为i的参数,并且由于调度应用程序(Appworx ... ugh)没有运行一个定义i =某事,所以这很难失败。
有没有办法在这方面做间接,这样我可以迭代,但是许多碰巧对于给定的程序是正确的?
答案 0 :(得分:1)
您想制作动态SQL,并且不知道将涉及多少参数。 Asktom has the authoritative answer for this。不要理会“新”方法。这对你不起作用,因为你不知道会有多少参数。
基本上,您将通过连接创建动态sql,但参数将存储在sys_context
中,以便查询将具有绑定。这有助于将SQL注入作为奖励。
答案 1 :(得分:1)
您可以使用new_value和默认SQL * Plus参数来解决此问题。
创建一个这样的脚本,例如test.sql:
-- hide output
set termout off
-- define parameter variables to be set with new_value
col par1 new_value 1 noprint
col par2 new_value 2 noprint
col par3 new_value 3 noprint
-- initialize parameter variables
select 1 par1, 2 par2, 3 par3 from dual where 1=2;
-- append comma to parameter variables, not needed for first parameter
select nullif(','||'&2',',') par2, nullif(','||'&3',',') par3 from dual;
-- show output
set termout on
-- you actual script starts here
prompt calling procedure my_proc(&1 &2 &3)
-- for next run
undef 1
undef 2
undef 3
现在拨打@test 3 4
输出:
calling procedure my_proc(3 ,4 )
或致电@test 1 2 3
输出:
calling procedure my_proc(1 ,2 ,3 )
现在您需要将此扩展到参数的最大预期数量。
(请注意,您必须登录才能使其正常工作,否则select from dual
将无声地失败。)