Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Como remover o valor específico da string separada por vírgulas no oracle


Aqui está uma solução que usa apenas funções de string padrão (em vez de expressões regulares) - o que deve resultar em execução mais rápida na maioria dos casos; remove 3 somente quando é o primeiro caractere seguido de vírgula, o último caractere precedido de vírgula, ou precedido e seguido de vírgula, e remove a vírgula que o precede no caso do meio e remove a vírgula que o segue no primeiro e terceiro caso.

Ele é capaz de remover dois 3's seguidos (o que algumas das outras soluções oferecidas não são capazes de fazer) enquanto deixa vírgulas consecutivas no lugar (que presumivelmente representam NULL) e não perturba números como 38 ou 123.

A estratégia é primeiro dobrar cada vírgula (substituir , com ,, ) e acrescentar e preceder uma vírgula (no início e no final da string). Em seguida, remova todas as ocorrências de ,3, . Do que resta, substitua cada ,, de volta com um único , e, finalmente, remova o , inicial e 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.

Observação Conforme apontado por MT0 (veja Comentários abaixo), isso cortará muito se a string original começar ou terminar com vírgulas. Para cobrir esse caso, em vez de envolver tudo dentro de trim(both ',' from ...) Eu deveria envolver o resto em uma subconsulta e usar algo como substr(new_str, 2, length(new_str) - 2) na consulta externa.