Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Wie man das Vorkommen von Trennzeichen in Zeichenfolgen zählt, außer denen in Anführungszeichen

Erst den abgegrenzten Inhalt eliminieren, danach zählen:

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

Die Verschachtelung von regexp_replace Aufrufe sind leider notwendig, um aufeinanderfolgende durch Anführungszeichen getrennte Felder korrekt zu behandeln:jedes trennende Komma wird vom Regexp-Muster verbraucht und wird daher für den nachfolgenden Vergleich nicht berücksichtigt.

Die regulären Ausdrücke von Oracle unterstützen den Lookahead-Operator nicht, was der natürliche Weg wäre, mit dieser Situation umzugehen.

Angesichts des Leistungseinbruchs von regexp_...-Aufrufen ist es möglicherweise besser,

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

Vorbehalt

Diese Lösung verarbeitet keine dquotes innerhalb von Feldwerten, die normalerweise als "" dargestellt werden oder \" .

Der erstere Fall lässt sich elegant handhaben:Anstatt einen "" zu interpretieren Betrachten Sie innerhalb eines durch Anführungszeichen getrennten Felds den gesamten Feldinhalt als Nebeneinanderstellung von 1 oder mehreren durch Anführungszeichen getrennten Zeichenfolgen, die keine Anführungszeichen enthalten. Während Sie bei der Verarbeitung der Daten nicht dieser Route folgen würden (alle dquotes würden verloren gehen), können Sie diese Perspektive zum Zählen verwenden:

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

Testfälle

-- 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;