Aquí hay una solución que usa solo funciones de cadena estándar (en lugar de expresiones regulares), lo que debería resultar en una ejecución más rápida en la mayoría de los casos; elimina 3 solo cuando es el primer carácter seguido de coma, el último carácter precedido de coma, o precedido y seguido de coma, y elimina la coma que lo precede en el caso central y elimina la coma que lo sigue en el primer y tercer caso.
Es capaz de eliminar dos 3 seguidos (lo que algunas de las otras soluciones ofrecidas no pueden hacer) mientras deja en su lugar comas consecutivas (que presumiblemente reemplazan a NULL) y no altera números como 38 o 123.
La estrategia es primero duplicar cada coma (reemplazar ,
con ,,
) y agregue y anteponga una coma (al principio y al final de la cadena). Luego elimine todas las apariciones de ,3,
. De lo que queda, reemplace cada ,,
de vuelta con un solo ,
y finalmente elimine el ,
inicial y final .
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.
Nota Como lo señaló MT0 (ver Comentarios a continuación), esto recortará demasiado si la cadena original comienza o termina con comas. Para cubrir ese caso, en lugar de envolver todo dentro de trim(both ',' from ...)
Debería envolver el resto dentro de una subconsulta y usar algo como substr(new_str, 2, length(new_str) - 2)
en la consulta externa.