Ето решение, което използва само стандартни низови функции (вместо регулярни изрази) - което трябва да доведе до по-бързо изпълнение в повечето случаи; той премахва 3 само когато е първият знак, последван от запетая, последният знак, предшестван от запетая, или предшестван и последван от запетая, и премахва запетаята, която го предхожда в средния регистър, и премахва запетаята, която го следва в първи и трети случай.
Той е в състояние да премахне две 3-ки подред (което някои от другите предлагани решения не могат да направят), като същевременно оставя на място последователни запетаи (които вероятно заместват NULL) и не смущава числа като 38 или 123.
Стратегията е първо да удвоите всяка запетая (заменете ,
с ,,
) и добавете и добавете запетая (в началото и в края на низа). След това премахнете всяко срещане на ,3,
. От това, което е останало, заменете всеки ,,
обратно с един ,
и накрая премахнете водещия и завършващия ,
.
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.
Забележка Както е посочено от MT0 (вижте коментарите по-долу), това ще отреже твърде много, ако оригиналният низ започва или завършва със запетаи. За да покриете този случай, вместо да опаковате всичко в trim(both ',' from ...)
Трябва да обвия останалото в подзаявка и да използвам нещо като substr(new_str, 2, length(new_str) - 2)
във външната заявка.