U mag de door komma's gescheiden lijst doorgeven als parameter (bindvariabele), maar u bent verantwoordelijk voor het ontleden ervan in een subquery. Een oplossing gebaseerd op deze thread gebruikt regexp_substr.
CREATE or REPLACE PROCEDURE p_getdata(A IN VARCHaR2, cur OUT sys_refcursor)
AS
BEGIN
open cur for 'with t1 as (select :A col from dual),
t2 as (select level lvl,to_number(regexp_substr(col,''[^,]+'', 1, level)) col
from t1 connect by regexp_substr(col, ''[^,]+'', 1, level) is not null)
select col as id from t2' using A;
END;
/
De procedure is vereenvoudigd, maar zou een idee moeten geven hoe het te gebruiken.
Het grote voordeel ten opzichte van het gebruik van dynamische SQL (aaneenschakeling van strings) is dat u de instructie niet bij elke uitvoering hoeft te ontleden. Om nog maar te zwijgen over de beveiliging (angst voor SQL-injectie).
Gebruik:
DECLARE
l_cur SYS_REFCURSOR;
l_id NUMBER;
BEGIN
p_getdata('1,1000,282828,4',l_cur);
LOOP
FETCH l_cur INTO l_id ;
EXIT WHEN l_cur%NOTFOUND;
dbms_output.put_line(l_id);
END LOOP;
END;
/
1
1000
282828
4
UPDATE
De bovenstaande procedure is vereenvoudigd, om uw functionaliteit te krijgen, moet u een zoekopdracht als deze in de CURSOR gebruiken (d.w.z. splits eerst alle drie de parameters in afzonderlijke subquery's met behulp van subquery-factoring, pas dan de resultaten toe in uw query)
CREATE or REPLACE PROCEDURE p_getdata(A IN VARCHAR2, B in VARCHAR2, c in VARCHAR2, cur OUT sys_refcursor)
AS
BEGIN
open cur for 'with ta1 as (select :A col from dual),
ta2 as (select level lvl,to_number(regexp_substr(col,''[^,]+'', 1, level)) col
from ta1 connect by regexp_substr(col, ''[^,]+'', 1, level) is not null),
tb1 as (select :B col from dual),
tb2 as (select level lvl,to_number(regexp_substr(col,''[^,]+'', 1, level)) col
from tb1 connect by regexp_substr(col, ''[^,]+'', 1, level) is not null),
tc1 as (select :C col from dual),
tc2 as (select level lvl,to_number(regexp_substr(col,''[^,]+'', 1, level)) col
from tc1 connect by regexp_substr(col, ''[^,]+'', 1, level) is not null)
select firstname, lastname, streetname, city
from mytable
where zip IN (select col from ta2) AND
streetnumber IN (select col from tb2) AND
apt_num in (select col from tc2)' using A, B, C;
END;
/
test geslaagd
DECLARE
l_cur SYS_REFCURSOR;
l_firstname VARCHAR2(20);
l_lastname VARCHAR2(20);
l_streetname VARCHAR2(20);
l_city VARCHAR2(20);
BEGIN
p_getdata('1100,,1200','1,2','11,12' ,l_cur);
LOOP
FETCH l_cur INTO l_firstname, l_lastname, l_streetname, l_city;
EXIT WHEN l_cur%NOTFOUND;
dbms_output.put_line(l_firstname|| ' ' || l_lastname || ' ' || l_streetname || ' ' || l_city);
END LOOP;
END;
/