Zapytanie, które próbujesz uzyskać:
SELECT id, split_function(city) FROM COMMA_SEPERATED
nie zadziała, ponieważ próbujesz zwrócić wiele wierszy dla każdego wiersza źródłowego. Musisz to niestety nieco bardziej skomplikować.
Jeśli celem jest ukrycie mechanizmu dzielenia, to najbliższym, o jakim przychodzi mi do głowy, jest utworzenie funkcji, która zwraca kolekcję ciągów, którą może być potokowe :
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;
/
Zaproponowane połączenie dałoby wtedy jeden wiersz na identyfikator z kolekcją:
select id, split_function(city) from comma_seperated;
ID SPLIT_FUNCTION(CITY)
---------- -----------------------------------------------------------------
1 ODCIVARCHAR2LIST('CHENNAI', 'HYDERABAD', 'JABALPUR')
2 ODCIVARCHAR2LIST('BHOPAL', 'PUNE')
co nie jest tym, czego chcesz; ale możesz użyć wyrażenia kolekcji tabel i połączenia krzyżowego, aby przekonwertować je na wiele wierszy:
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
To nie jest tak proste, jak się spodziewałeś, ale prawdopodobnie nadal jest lepsze niż łączenie krzyżowe z xmltable()
, szczególnie jeśli chcesz ponownie wykorzystać tę logikę/funkcję dzielenia w wielu miejscach, a także ukryć szczegóły wykonania podziału - co pozwoliłoby Ci łatwo zmienić mechanizm, gdybyś chciał, np. aby użyć bardziej popularnego wyrażenia regularnego do wykonania podziału.