Opa..
Um tempo atrás eu criei uma função que pega uma string separada por vírgulas e retorna como registros, ou seja, um PIPELINED bem simples...
Selecionar tudo
CREATE OR REPLACE FUNCTION fct_comma_to_table_pipelined(p_string VARCHAR2) RETURN varchar_list_type
PIPELINED IS
RESULT varchar_list_type;
v_string VARCHAR2(32000);
v_next NUMBER;
v_start NUMBER;
v_count NUMBER;
--/ Busca o índice da próxima vírgula
FUNCTION NEXT(p_last_index NUMBER) RETURN NUMBER IS
BEGIN
IF (p_last_index IS NOT NULL)
THEN
RETURN(INSTR(v_string, ',', p_last_index));
END IF;
RETURN(INSTR(v_string, ','));
END NEXT;
--/
BEGIN
--/
v_string := p_string;
--/
IF v_string IS NOT NULL
THEN
IF INSTR(v_string, ',', -1) <> LENGTH(v_string)
THEN
v_string := v_string || ',';
END IF;
WHILE NVL(v_next, 0) <> LENGTH(v_string)
LOOP
v_start := NVL(v_next, 0) + 1;
v_next := NEXT(v_next + 1);
v_count := v_next - v_start;
PIPE ROW(SUBSTR(v_string, v_start, v_count));
END LOOP;
END IF;
RETURN;
END fct_comma_to_table_pipelined;
O uso dela seria algo assim...
Selecionar tudo
SQL> SELECT *
2 FROM TABLE(fct_comma_to_table_pipelined('1,2,3'));
COLUMN_VALUE
--------------------------------------------------------------------------------
1
2
3
Bueno, tendo entendido a função vamos ao teu problema
O problema do teu código é que tu estas comparando uma string com um campo number.
Usando a "minha" função tu podes usar a tua mesma query no IN.
Selecionar tudo
SQL> SELECT *
2 FROM (SELECT LEVEL nivel
3 FROM dual
4 CONNECT BY LEVEL <= 30)
5 WHERE TO_CHAR(nivel) IN (SELECT *
6 FROM TABLE(fct_comma_to_table_pipelined((SELECT REPLACE(s_sparam, '#', ',')
7 FROM (SELECT '1#2#5#8#25' s_sparam
8 FROM dual)))));
NIVEL
---------
1
2
25
5
8