Заявката, до която се опитвате да стигнете:
SELECT id, split_function(city) FROM COMMA_SEPERATED
няма да работи, защото се опитвате да върнете множество редове за всеки изходен ред. За съжаление трябва да го направите малко по-сложно от това.
Ако целта е да скрия механизма за разделяне, тогава най-близкото, за което мога да се сетя, е да създам функция, която връща колекция от низове, което може да бъде конвейерно :
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;
/
След това вашето предложено извикване ще ви даде по един ред за ID с колекция:
select id, split_function(city) from comma_seperated;
ID SPLIT_FUNCTION(CITY)
---------- -----------------------------------------------------------------
1 ODCIVARCHAR2LIST('CHENNAI', 'HYDERABAD', 'JABALPUR')
2 ODCIVARCHAR2LIST('BHOPAL', 'PUNE')
което не е точно това, което искате; но вместо това можете да използвате израз за колекция от таблици и кръстосано свързване, за да конвертирате в множество редове:
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
Това не е толкова просто, колкото се надявахте, но може би все още е по-добро от кръстосаното свързване към xmltable()
, особено ако искате да използвате повторно тази логика/функция за разделяне на множество места, както и да скриете подробностите за това как се извършва разделянето - което ще ви позволи лесно да промените механизма, ако искате, напр. за да използвате по-често срещан регулярен израз за извършване на разделянето.