Hier is een oplossing die alleen standaard tekenreeksfuncties gebruikt (in plaats van reguliere expressies) - wat in de meeste gevallen tot een snellere uitvoering zou moeten leiden; het verwijdert 3 alleen als het het eerste teken is gevolgd door een komma, het laatste teken voorafgegaan door een komma, of voorafgegaan en gevolgd door een komma, en het verwijdert de komma die eraan voorafgaat in de middelste hoofdletter en het verwijdert de komma die erop volgt in de eerste en derde geval.
Het is in staat om twee 3's achter elkaar te verwijderen (wat sommige van de andere aangeboden oplossingen niet kunnen doen) terwijl opeenvolgende komma's op hun plaats blijven (die vermoedelijk voor NULL staan) en getallen zoals 38 of 123 niet storen.
De strategie is om eerst elke komma te verdubbelen (vervang ,
met ,,
) en voeg een komma toe en voeg een komma toe (aan het begin en het einde van de tekenreeks). Verwijder vervolgens elk voorkomen van ,3,
. Van wat er over is, vervang elke ,,
terug met een enkele ,
en verwijder ten slotte de voor- en achterliggende ,
.
with
test_data ( str ) as (
select '1,2,3,4,5' from dual union all
select '1,2,3,3,4,4,5' from dual union all
select '12,34,5' from dual union all
select '1,,,3,3,3,4' from dual
)
select str,
trim(both ',' from
replace( replace(',' || replace(str, ',', ',,') || ',', ',3,'), ',,', ',')
) as new_str
from test_data
;
STR NEW_STR
------------- ----------
1,2,3,4,5 1,2,4,5
1,2,3,3,4,4,5 1,2,4,4,5
12,34,5 12,34,5
1,,,3,3,3,4 1,,,4
4 rows selected.
Opmerking Zoals aangegeven door MT0 (zie opmerkingen hieronder), wordt dit te veel bijgesneden als de originele tekenreeks begint of eindigt met komma's. Om dat te dekken, in plaats van alles te verpakken in trim(both ',' from ...)
Ik zou de rest in een subquery moeten stoppen en zoiets als substr(new_str, 2, length(new_str) - 2)
moeten gebruiken in de buitenste vraag.