Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Jak liczyć wystąpienia separatora w ciągu znaków z wyjątkiem tych w cudzysłowach?

Najpierw usuń oddzieloną zawartość, a potem policz:

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

Zagnieżdżenie regexp_replace Wywołania są niestety niezbędne do poprawnej obsługi kolejnych pól oddzielonych cudzysłowami:każdy przecinek oddzielający jest zużywany przez wzorzec wyrażenia regularnego, a zatem nie zostanie uwzględniony w kolejnym dopasowaniu.

Regexeny Oracle nie obsługują operatora lookahead, co byłoby naturalnym sposobem radzenia sobie z tą sytuacją.

Biorąc pod uwagę wydajność wywołań regexp_..., lepiej byłoby użyć

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

Zastrzeżenie

To rozwiązanie nie obsługuje dquotes w wartościach pól, które są zwykle reprezentowane jako "" lub \" .

Pierwsza sprawa może być obsługiwana elegancko:Zamiast interpretować "" wewnątrz pola rozdzielonego cudzysłowami, rozważ całą zawartość pola jako zestawienie jednego lub więcej ciągów oddzielonych cudzysłowami, które nie zawierają dquote. Chociaż nie podążałbyś tą ścieżką podczas przetwarzania danych (wszystkie dquote zostałyby utracone), możesz wykorzystać tę perspektywę w celu liczenia:

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

Przypadki testowe

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


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Problem z wymianą referencji w Visual Studio-ASP.NET

  2. Błąd :ORA-00907:brak prawego nawiasu

  3. Oracle automatycznie zmienia nazwy kolumn z wybierz?

  4. Źródło danych JNDI do Oracle z Grails 1.3

  5. oracle błąd rozpoznawania nazw funkcji pl/sql