Frågan du försöker komma till:
SELECT id, split_function(city) FROM COMMA_SEPERATED
kommer inte att fungera, eftersom du försöker returnera flera rader för varje källrad. Du måste göra det lite mer komplicerat än så tyvärr.
Om målet är att dölja uppdelningsmekanismen är det närmaste jag kan komma på att skapa en funktion som returnerar en samling strängar, som kan vara pipelined :
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;
/
Ditt föreslagna samtal skulle då ge dig en rad per ID med en samling:
select id, split_function(city) from comma_seperated;
ID SPLIT_FUNCTION(CITY)
---------- -----------------------------------------------------------------
1 ODCIVARCHAR2LIST('CHENNAI', 'HYDERABAD', 'JABALPUR')
2 ODCIVARCHAR2LIST('BHOPAL', 'PUNE')
vilket inte riktigt är vad du vill ha; men du kan använda ett tabellsamlingsuttryck och cross-join för att konvertera till flera rader istället:
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
Det är inte så enkelt som du hoppats på, men är utan tvekan fortfarande bättre än att korsansluta till xmltable()
, särskilt om du vill återanvända den delande logiken/funktionen på flera ställen, samt dölja detaljerna om hur uppdelningen går till - vilket skulle låta dig ändra mekanismen enkelt om du ville, t.ex. att använda ett vanligare reguljärt uttryck för att göra uppdelningen.