De zoekopdracht die u probeert te bereiken:
SELECT id, split_function(city) FROM COMMA_SEPERATED
zal niet werken, omdat u meerdere rijen probeert te retourneren voor elke bronrij. Je moet het helaas wat ingewikkelder maken dan dat.
Als het doel is om het splitsingsmechanisme te verbergen, dan is het beste wat ik kan bedenken het creëren van een functie die een verzameling strings retourneert, wat zou kunnen zijn gepipelined :
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;
/
Uw voorgestelde oproep geeft u dan één rij per ID met een verzameling:
select id, split_function(city) from comma_seperated;
ID SPLIT_FUNCTION(CITY)
---------- -----------------------------------------------------------------
1 ODCIVARCHAR2LIST('CHENNAI', 'HYDERABAD', 'JABALPUR')
2 ODCIVARCHAR2LIST('BHOPAL', 'PUNE')
wat niet helemaal is wat je wilt; maar u kunt in plaats daarvan een tabelverzamelingsuitdrukking en cross-join gebruiken om naar meerdere rijen te converteren:
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
Dat is niet zo eenvoudig als je had gehoopt, maar het is aantoonbaar nog steeds beter dan cross-joining naar de xmltable()
, vooral als u die splitsingslogica/functie op meerdere plaatsen wilt hergebruiken, en ook de details wilt verbergen van hoe de splitsing wordt uitgevoerd - waardoor u het mechanisme gemakkelijk kunt wijzigen als u dat wilt, b.v. om een meer algemene reguliere expressie te gebruiken om de splitsing uit te voeren.