CREATE OR REPLACE FUNCTION PARSER_FUNCTION(
inputString IN VARCHAR2,
index IN NUMBER
)
RETURN VARCHAR2 DETERMINISTIC
AS
RETURN REGEXP_SUBSTR( inputString, '[[:alpha:]]+', 1, index );
END PARSER_FUNCTION;
/
Or, without regular expressions:
CREATE OR REPLACE FUNCTION parser_function(
list IN VARCHAR2,
position IN NUMBER,
delimiter IN VARCHAR2 DEFAULT ','
)
RETURN VARCHAR2 DETERMINISTIC
IS
p_start NUMBER := 1;
p_end NUMBER;
BEGIN
IF list IS NULL OR position < 1 THEN
RETURN NULL;
END IF;
IF position > 1 THEN
p_start := INSTR( list, delimiter, 1, position - 1 ) + 1;
IF p_start = 1 THEN
RETURN NULL;
END IF;
END IF;
p_end := INSTR( list, delimiter, 1, position );
IF p_end = 0 THEN
p_end := LENGTH( list ) + 1;
END IF;
RETURN SUBSTR( list, p_start, p_end - p_start );
END;
/
Then you can just do:
WHERE table_column LIKE '%' || PARSER_FUNCTION( 'list,list2,list3', 1 ) || '%'
AND table_column LIKE '%' || PARSER_FUNCTION( 'list,list2,list3', 2 ) || '%'
AND table_column LIKE '%' || PARSER_FUNCTION( 'list,list2,list3', 3 ) || '%'
AND table_column LIKE '%' || PARSER_FUNCTION( 'list,list2,list3', 4 ) || '%'
AND table_column LIKE '%' || PARSER_FUNCTION( 'list,list2,list3', 5 ) || '%'
(Note: This will work for when you are using AND
in the where clause but might not when you are using OR
as the 4th and 5th entries in the list don't exist so you will get a clause AND table_column LIKE '%%'
which will always be true so you could need a bit more defensive coding to check if the return from the PARSER_FUNCTION
is not NULL
.)
Or you could just get rid of the function:
WHERE table_column LIKE '%' || REGEXP_SUBSTR( 'list,list2,list3', '[[:alpha:]]+', 1, 1 ) || '%'
AND table_column LIKE '%' || REGEXP_SUBSTR( 'list,list2,list3', '[[:alpha:]]+', 1, 2 ) || '%'
AND table_column LIKE '%' || REGEXP_SUBSTR( 'list,list2,list3', '[[:alpha:]]+', 1, 3 ) || '%'
AND table_column LIKE '%' || REGEXP_SUBSTR( 'list,list2,list3', '[[:alpha:]]+', 1, 4 ) || '%'
AND table_column LIKE '%' || REGEXP_SUBSTR( 'list,list2,list3', '[[:alpha:]]+', 1, 5 ) || '%'
Update:
You could also convert the list to a collection and join that to your query:
CREATE OR REPLACE FUNCTION split_String(
i_str IN VARCHAR2,
i_delim IN VARCHAR2 DEFAULT ','
) RETURN SYS.ODCIVARCHAR2LIST DETERMINISTIC
AS
p_result SYS.ODCIVARCHAR2LIST := SYS.ODCIVARCHAR2LIST();
p_start NUMBER(5) := 1;
p_end NUMBER(5);
c_len CONSTANT NUMBER(5) := LENGTH( i_str );
c_ld CONSTANT NUMBER(5) := LENGTH( i_delim );
BEGIN
IF c_len > 0 THEN
p_end := INSTR( i_str, i_delim, p_start );
WHILE p_end > 0 LOOP
p_result.EXTEND;
p_result( p_result.COUNT ) := SUBSTR( i_str, p_start, p_end - p_start );
p_start := p_end + c_ld;
p_end := INSTR( i_str, i_delim, p_start );
END LOOP;
IF p_start <= c_len + 1 THEN
p_result.EXTEND;
p_result( p_result.COUNT ) := SUBSTR( i_str, p_start, c_len - p_start + 1 );
END IF;
END IF;
RETURN p_result;
END;
/
Then you can just do:
SELECT *
FROM your_table t
WHERE NOT EXISTS( SELECT 1
FROM TABLE( split_String( 'list1,list2,list3' ) l
WHERE t.table_column NOT LIKE '%' || l.COLUMN_VALUE || '%' )
This means your list can contain any number of elements and it will check them all without having to repeatedly call extract the list item using regular expressions.