La query a cui stai tentando di accedere:
SELECT id, split_function(city) FROM COMMA_SEPERATED
non funzionerà, perché stai cercando di restituire più righe per ogni riga di origine. Devi renderlo un po' più complicato di così, sfortunatamente.
Se l'obiettivo è nascondere il meccanismo di divisione, la cosa più vicina a cui riesco a pensare è creare una funzione che restituisca una raccolta di stringhe, che potrebbe essere condotto :
create or replace function split_function (p_string varchar2)
return sys.odcivarchar2list pipelined as
begin
for r in (
select result
from xmltable (
'if (contains($X,",")) then ora:tokenize($X,"\,") else $X'
passing p_string as x
columns result varchar2(4000) path '.'
)
)
loop
pipe row (trim(r.result));
end loop;
end split_function;
/
La chiamata proposta ti darebbe quindi una riga per ID con una raccolta:
select id, split_function(city) from comma_seperated;
ID SPLIT_FUNCTION(CITY)
---------- -----------------------------------------------------------------
1 ODCIVARCHAR2LIST('CHENNAI', 'HYDERABAD', 'JABALPUR')
2 ODCIVARCHAR2LIST('BHOPAL', 'PUNE')
che non è proprio quello che vuoi; ma puoi invece utilizzare un'espressione di raccolta di tabelle e unire incrociati per convertire in più righe:
select cs.id, t.column_value as city
from comma_seperated cs
cross join table(split_function(cs.city)) t;
ID CITY
---------- ------------------------------
1 CHENNAI
1 HYDERABAD
1 JABALPUR
2 BHOPAL
2 PUNE
Non è così semplice come speravi, ma è probabilmente ancora meglio del cross-join a xmltable()
, in particolare se desideri riutilizzare quella logica/funzione di divisione in più punti, oltre a nascondere i dettagli di come viene eseguita la divisione, il che ti consentirebbe di modificare facilmente il meccanismo se lo desideri, ad es. per utilizzare un'espressione regolare più comune per eseguire la divisione.