Reputation: 5473
I'm trying to write a sql*plus script that runs a single arbitrary procedure. The tricky part is that I want to be able to run the procedure regardless of how many parameters that procedure takes.
To figure out the correct number of arguments for the procedure, I'm doing the following:
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';
When it comes time to build the execute-immediate string, I wanted to use a loop of some sort to do that. The parameters are all being pass in are just numbered, &1 through &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;
This doesn't work however. It sees &i and of course thinks that it is a parameter named i, and since the scheduling application (Appworx... ugh) isn't running a define i=something, this fails miserably.
Is there any way to do indirection in this, such that I can iterate through however many happens to be correct for the given procedure?
Upvotes: 1
Views: 850
Reputation: 2787
You can trick this with new_value and defaulting SQL*Plus parameters.
Create a script like that, say for example 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
Now call with @test 3 4
Output:
calling procedure my_proc(3 ,4 )
Or call with @test 1 2 3
Output:
calling procedure my_proc(1 ,2 ,3 )
Now you need to extend to this to the maximum expected number of your parameters.
(Note you have to be logged on to make this work, otherwise the select from dual
will fail silently.)
Upvotes: 1
Reputation:
You want to make dynamic sql and don't know how many parameters will be involved. Asktom has the authoritative answer for this. Don't bother with the "new" method. It won't work for you, as you don't know how many parameters there will be.
Basically, you will create your dynamic sql by concatenation, but the parameters will be stored in a sys_context
so that the query will have binds. This help with things like SQL injection as a bonus.
Upvotes: 1