Berikut adalah solusi yang hanya menggunakan fungsi string standar (bukan ekspresi reguler) - yang seharusnya menghasilkan eksekusi yang lebih cepat dalam banyak kasus; itu menghapus 3 hanya ketika itu adalah karakter pertama diikuti dengan koma, karakter terakhir didahului dengan koma, atau didahului dan diikuti oleh koma, dan menghapus koma yang mendahuluinya di tengah dan menghapus koma yang mengikutinya di kasus pertama dan ketiga.
Itu dapat menghapus dua 3 berturut-turut (yang tidak dapat dilakukan oleh beberapa solusi lain yang ditawarkan) sambil meninggalkan koma berturut-turut (yang mungkin berarti NULL) dan tidak mengganggu angka seperti 38 atau 123.
Strateginya adalah menggandakan dulu setiap koma (ganti ,
dengan ,,
) dan tambahkan dan tambahkan koma (ke awal dan akhir string). Kemudian hapus setiap kemunculan ,3,
. Dari yang tersisa, ganti setiap ,,
kembali dengan satu ,
dan terakhir hapus ,
.
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.
Catatan Seperti yang ditunjukkan oleh MT0 (lihat Komentar di bawah), ini akan memangkas terlalu banyak jika string asli dimulai atau diakhiri dengan koma. Untuk menutupi kasus itu, alih-alih membungkus semuanya dalam trim(both ',' from ...)
Saya harus membungkus sisanya dalam subquery, dan menggunakan sesuatu seperti substr(new_str, 2, length(new_str) - 2)
dalam kueri luar.