This alternative implementation of a varying IN list, which uses logic described at String to Rows: MODEL Method, only works only on Oracle 10g or above.
variable d varchar2 execute :d := ',' variable p varchar2(100) execute :p := '1,3,5' select * from t where key in ( select to_number( val ) from dual model return updated rows dimension by ( 0 as position ) measures ( :p || :d as val ) rules upsert ( val [ for position from 1 to length( regexp_replace( val[0], '[^'||:d||']', null ) ) increment 1 ] = rtrim( regexp_substr( val[0], '.*?' || :d, 1, cv(position) ), :d ) ) ) order by 1 ;
KEY C ---------- ---------- 1 v1 3 v3 5 v5
Duplicates in the IN list produce the same result as if there were no duplicates.
execute :p := '1,3,3,3,3,5' /
KEY C ---------- ---------- 1 v1 3 v3 5 v5
The query accepts IN lists with spaces.
execute :p := '1, 2, 3, 4, 5' /
KEY C ---------- ---------- 1 v1 2 v2 3 v3 4 v4 5 v5
If the IN list is null no rows are returned.
execute :p := null PL/SQL procedure successfully completed. / no rows selected
For quoted string lists like 'v1', 'v3', 'v5' we can use a parsing technique described at String to Columns: Quoted Values - 10g+.
-- the delimiter is a single quote this time execute :d := '''' execute :p := q'['v1', 'v3', 'v5']' select * from t where c in ( select val from dual model return updated rows dimension by ( 0 as position ) measures ( :P as val ) rules upsert ( val [ for position from 1 to length( regexp_replace( val[0], '[^'||:d||']', null ) ) increment 1 ] = TRIM( :D FROM REGEXP_SUBSTR( VAL[0], :D || '.*?' || :D, 1, CV(POSITION) ) ) ) ) order by 1 ;
KEY C ---------- ---------- 1 v1 3 v3 5 v5