Tags

, , ,

One of the frequent question on Oracle forums is about the Varying IN list in WHERE clause. One such question was asked here http://stackoverflow.com/questions/27738359/select-from-table-with-varying-in-list-in-where-clause/27739139#27739139.

Let’s understand the issue.

Test case :

//DDLs to create the test tables

CREATE TABLE temp(ids VARCHAR2(4000));
CREATE TABLE temp_id(data_id NUMBER);

//DMLs to populate test data
INSERT INTO temp VALUES('1, 2, 3');

INSERT INTO temp_id VALUES(1);
INSERT INTO temp_id VALUES(2);
INSERT INTO temp_id VALUES(3);
INSERT INTO temp_id VALUES(4);
INSERT INTO temp_id VALUES(5);

Reason :

IN (‘1, 2, 3’) is NOT same as IN (1, 2, 3) OR IN(‘1’, ‘2’, ‘3’)

Hence,

SELECT * FROM temp_id WHERE data_id IN(SELECT ids FROM temp);

is same as

SELECT * FROM temp_id WHERE data_id IN('1, 2, 3');

which would thrown an error ORA-01722: invalid number –

SQL> SELECT * FROM temp_id WHERE data_id IN('1, 2, 3');
SELECT * FROM temp_id WHERE data_id IN('1, 2, 3')
*
ERROR at line 1:
ORA-01722: invalid number

SQL> SELECT * FROM temp_id WHERE data_id IN(SELECT ids FROM temp);
SELECT * FROM temp_id WHERE data_id IN(SELECT ids FROM temp)
*
ERROR at line 1:
ORA-01722: invalid number

Above is NOT same as

SELECT * FROM temp_id WHERE data_id IN(1, 2, 3);

which would give you correct output

SQL> SELECT * FROM temp_id WHERE data_id IN(1, 2, 3);

DATA_ID
----------
1
2
3

SQL>

So, ‘1, 2, 3’ is a single string, a single value in that in list.

Solution :

For such requirement, we can achieve it like this –

SQL> SELECT * FROM temp;

IDS
--------------------------------------------------------------
1, 2, 3

SQL> SELECT * FROM temp_id;

DATA_ID
----------
1
2
3
4
5

SQL>
SQL> WITH data AS
2 (SELECT to_number(trim(regexp_substr(ids, '[^,]+', 1, LEVEL))) ids
3 FROM temp
4 CONNECT BY instr(ids, ',', 1, LEVEL - 1) > 0
5 )
6 SELECT * FROM temp_id WHERE data_id IN
7 (SELECT ids FROM data
8 )
9 /

DATA_ID
----------
1
2
3

SQL>

Alternatively, you can create your own TABLE function or a Pipelined function to achieve this. Your goal should be to split the comma-separated IN list into different rows. How you do it is up to you!