Oracle
 sql >> Base de données >  >> RDS >> Oracle

Comment compter les occurrences de séparateur dans une chaîne à l'exclusion de celles entre guillemets

Éliminez d'abord le contenu délimité, comptez ensuite :

regexp_count (
    regexp_replace (
        regexp_replace (
            i.data_record
          , '(^|,)"[^"]*"(,|$)'
          , '\1\2'
        )
      , '(^|,)"[^"]*"(,|$)'
      , '\1\2'
    )
  , ',' 
) 

L'imbrication de regexp_replace est malheureusement nécessaire pour gérer correctement les champs consécutifs délimités par des guillemets :toute virgule de séparation est consommée par le modèle d'expression régulière et ne sera donc pas prise en compte pour la correspondance suivante.

L'expression régulière d'Oracle ne prend pas en charge l'opérateur d'anticipation, ce qui serait la manière naturelle de gérer cette situation.

Compte tenu des performances des appels regexp_..., vous feriez peut-être mieux d'utiliser

length(i.data_record) - length ( replace ( regexp_replace ( i.data_record, '(^|,)"[^"]*"(,|$)', '\1\2' ),',','' ) )

Mise en garde

Cette solution ne gère pas les dquotes dans les valeurs de champ, qui sont généralement représentées par "" ou \" .

Le premier cas peut être traité avec élégance :au lieu d'interpréter un "" à l'intérieur d'un champ délimité par des guillemets, considérez l'ensemble du contenu du champ comme une juxtaposition d'une ou plusieurs chaînes délimitées par des guillemets qui ne contiennent pas de guillemets. Bien que vous ne suiviez pas cette voie dans le traitement des données (toutes les citations seraient perdues), vous pouvez utiliser cette perspective pour le plaisir de compter :

regexp_count (
    regexp_replace (
        regexp_replace (
            i.data_record
          , '(^|,)("[^"]*")+(,|$)'  -- changed
          , '\1\3'                  -- changed
        )
      , '(^|,)("[^"]*")+(,|$)'   -- changed
      , '\1\3'                   -- changed
    )
  , ',' 
) 

Cas de test

-- works
select regexp_count ( regexp_replace ( regexp_replace ( '1,"data,and more so","more data,and even more so"', '(^|,)"[^"]*"(,|$)', '\1\2' ), '(^|,)"[^"]*"(,|$)', '\1\2' ), ',' ) from dual;
select regexp_count ( regexp_replace ( regexp_replace ( '1,"data,and more so",2,"more data,and even more so"', '(^|,)"[^"]*"(,|$)', '\1\2' ), '(^|,)"[^"]*"(,|$)', '\1\2' ), ',' ) from dual;

select regexp_count ( regexp_replace ( regexp_replace ( '1,"""data"",and more so",2,"more data,and even more so"', '(^|,)("[^"]*")+(,|$)', '\1\3' ), '(^|,)("[^"]*")+(,|$)', '\1\3' ), ',' ) from dual;

-- fails
select regexp_count ( regexp_replace ( '1,"data,and more so","more data,and even more so"', '(^|,)"[^"]*"(,|$)', '\1\2' ), ',' ) from dual;
select regexp_count ( regexp_replace ( '1,"data,and more so",2,"more data,and even more so"', '(^|,)"[^"]*"(,|$)', '\1\2' ), ',' ) from dual;