Zde je řešení, které používá pouze standardní řetězcové funkce (spíše než regulární výrazy) – což by ve většině případů mělo vést k rychlejšímu provádění; odstraní 3 pouze v případě, že se jedná o první znak, za kterým následuje čárka, poslední znak před čárkou nebo před a následovaný čárkou a odstraní čárku, která mu předchází v prostředním případě a odstraní čárku, která za ním následuje v první a třetí případ.
Je schopen odstranit dvě 3 v řadě (což některá jiná nabízená řešení nedokážou) a zároveň ponechat na místě po sobě jdoucí čárky (které pravděpodobně nahrazují NULL) a nerušit čísla jako 38 nebo 123.
Strategií je nejprve zdvojnásobit každou čárku (nahradit ,
s ,,
) a připojit a předřadit čárku (na začátek a konec řetězce). Poté odstraňte každý výskyt ,3,
. Z toho, co zbylo, nahraďte každý ,,
zpět pomocí jediného ,
a nakonec odstraňte úvodní a koncové ,
.
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.
Poznámka Jak zdůraznil MT0 (viz komentáře níže), toto se příliš ořízne, pokud původní řetězec začíná nebo končí čárkami. Abychom pokryli tento případ, místo toho, abychom vše zabalili do trim(both ',' from ...)
Zbytek bych měl zabalit do poddotazu a použít něco jako substr(new_str, 2, length(new_str) - 2)
ve vnějším dotazu.