The object is to dynamically assemble an instruction from a variable number of filters in a WHERE clause. I'm not sure where recursion fits into all of this, so I just use an array to handle the parameters:
SQL> create type qry_param as object 2 (col_name varchar2(30) 3 , col_value varchar(20)) 4 / Type created. SQL> create type qry_params as table of qry_param 2 / Type created. SQL>
This table is passed to a function that moves around the array. For each record in the array, it adds a line to the WHERE clause in the format <name> = '<value>'. You will probably need more complex filtering — different operators, explicit data type conversions, variable bindings — but this is a general idea.
SQL> create or replace function get_emps 2 (p_args in qry_params ) 3 return sys_refcursor 4 as 5 stmt varchar2(32767); 6 rc sys_refcursor; 7 begin 8 stmt := ' select * from emp'; 9 for i in p_args.first()..p_args.last() 10 loop 11 if i = 1 then 12 stmt := stmt || ' where '; 13 else 14 stmt := stmt || ' and '; 15 end if; 16 stmt := stmt || p_args(i).col_name 17 ||' = '''||p_args(i).col_value||''''; 18 end loop; 19 open rc for stmt; 20 return rc; 21 end get_emps; 22 / Function created. SQL>
Finally, to execute this query, we need to populate a local variable of array type and return the result to the ref cursor.
SQL> var l_rc refcursor SQL> declare 2 l_args qry_params := qry_params 3 (qry_param('DEPTNO', '50') 4 , qry_param('HIREDATE', '23-MAR-2010')); 5 begin 6 :l_rc := get_emps(l_args); 7 end; 8 / PL/SQL procedure successfully completed. SQL> print l_rc EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ---------- ---------- --------- ---------- --------- ---------- ---------- ---------- 8041 FEUERSTEIN PLUMBER 7839 23-MAR-10 4250 50 8040 VERREYNNE PLUMBER 7839 23-MAR-10 4500 50 SQL>
change
In the last paragraph of their question, OP says that they use XML to pass criteria. This requirement does not change the form of my initial implementation. The loop should just disable the XPath query instead of the array:
SQL> create or replace function get_emps 2 (p_args in xmltype ) 3 return sys_refcursor 4 as 5 stmt varchar2(32767); 6 rc sys_refcursor; 7 begin 8 stmt := ' select * from emp'; 9 for i in (select * from xmltable ( 10 '/params/param' 11 passing p_args 12 columns 13 position for ordinality 14 , col_name varchar2(30) path '/param/col_name' 15 , col_value varchar2(30) path '/param/col_value' 16 ) 17 ) 18 loop 19 if i.position = 1 then 20 stmt := stmt || ' where '; 21 else 22 stmt := stmt || ' and '; 23 end if; 24 stmt := stmt || i.col_name 25 ||' = '''||i.col_value||''''; 26 end loop; 27 open rc for stmt; 28 return rc; 29 end get_emps; 30 / Function created. SQL>
As you can see, this version returns the same results as before ...
SQL> var l_rc refcursor SQL> declare 2 l_args xmltype := xmltype 3 ('<params> 4 <param> 5 <col_name>DEPTNO</col_name> 6 <col_value>50</col_value> 7 </param> 8 <param> 9 <col_name>HIREDATE</col_name> 10 <col_value>23-MAR-2010</col_value> 11 </param> 12 </params>'); 13 begin 14 :l_rc := get_emps(l_args); 15 end; 16 / PL/SQL procedure successfully completed. SQL> print l_rc EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ---------- ---------- --------- ---------- --------- ---------- ---------- ---------- 8041 FEUERSTEIN PLUMBER 7839 23-MAR-10 4250 50 8040 VERREYNNE PLUMBER 7839 23-MAR-10 4500 50 SQL>