PL / SQL does not have much to do with reflection. Of course, there is no equivalent to NAME_IN. I could not solve this using dynamic SQL, but I found a solution.
Here is an example. It has three procedures. Please note that all of them are required, but we can pass NULL in the parameter slot. This, of course, is one of my objections to such "soft coding": it confuses the API. Describing a procedure is no longer enough to know what arguments it requires.
create or replace procedure do_something (p1 in varchar2 , p2 in varchar2 , p3 in varchar2) is args sys.dbms_debug_vc2coll; begin args := new sys.dbms_debug_vc2coll(p1, p2, p3); for r in ( select s.varname, a.position from syscfg s join user_arguments a on (s.procname = a.object_name and s.varname = a.argument_name) where s.procname = 'DO_SOMETHING' and s.mandatory = 'Y' order by a.position ) loop if args(r.position) is null then raise_application_error(-20000, r.varname ||' cannot be null'); end if; end loop; dbms_output.put_line('Procedure executed successfully!'); end; /
Checking the "dynamic" parameter is done by filling the collection with parameters in the signature order. We get the position of the configured parameters by combining the presentation of the data dictionary with our configuration table. Then we use the position as an index for the array. Note that the collection accepts strings. I declared all my parameters as Varchars, but you may need to specify dates or numbers.
So, yes, this is awkward, but " > this avoidance quest often leads to [...] complexity, convolution, and many-sided, unreachable code. " :)
Here is the contents of the config table:
SQL> select * from syscfg 2 / PROCNAME VARNAME M ------------------------------ ------------------------------ - DO_SOMETHING P1 Y DO_SOMETHING P2 Y DO_SOMETHING P3 N SQL>
So let the roll!
SQL> set serveroutput on SQL> exec do_something('A', 'Y', null) Procedure executed successfully! PL/SQL procedure successfully completed. SQL> exec do_something('A', null, 'X') BEGIN do_something('A', null, 'X'); END; * ERROR at line 1: ORA-20000: P2 cannot be null ORA-06512: at "APC.DO_SOMETHING", line 24 ORA-06512: at line 1 SQL>
It looks good, but to prove that nothing is in my sleeve ....
SQL> update syscfg set mandatory = 'N' where varname = 'P2' / 2 3 4 1 row updated. SQL> select * from syscfg 2 / PROCNAME VARNAME M ------------------------------ ------------------------------ - DO_SOMETHING P1 Y DO_SOMETHING P2 N DO_SOMETHING P3 N SQL> exec do_something('A', null, 'X') Procedure executed successfully! PL/SQL procedure successfully completed. SQL>
Perhaps your customers are dumb enough to think that this ultra-flexible will be convenient in other places. The good news is that this solution can be easily retrieved into a standalone procedure that takes PROCNAME and an array as parameters.