Fjern først det afgrænsede indhold, tæl bagefter:
regexp_count (
regexp_replace (
regexp_replace (
i.data_record
, '(^|,)"[^"]*"(,|$)'
, '\1\2'
)
, '(^|,)"[^"]*"(,|$)'
, '\1\2'
)
, ','
)
Indlejringen af regexp_replace
opkald er desværre nødvendige for at håndtere på hinanden følgende felter afgrænset af anførselstegn korrekt:ethvert adskillelseskomma forbruges af regexp-mønsteret og vil derfor ikke blive taget i betragtning for det efterfølgende match.
Oracles regexen understøtter ikke lookahead-operatøren, hvilket ville være den naturlige måde at håndtere denne situation på.
I betragtning af præstationshittet af regexp_... opkald, er du måske bedre stillet til at bruge
length(i.data_record) - length ( replace ( regexp_replace ( i.data_record, '(^|,)"[^"]*"(,|$)', '\1\2' ),',','' ) )
Advarsel
Denne løsning håndterer ikke dcitater inden for feltværdier, som normalt er repræsenteret som ""
eller \"
.
Førstnævnte sag kan håndteres elegant:I stedet for at fortolke en ""
inde i et anførselssepareret felt skal du betragte hele feltindholdet som en sidestilling af 1 eller flere anførselsseparerede strenge, der ikke indeholder anførselstegn. Selvom du ikke ville følge denne rute i behandlingen af dataene (alle anførselstegn ville gå tabt), kan du bruge dette perspektiv for at tælle:
regexp_count (
regexp_replace (
regexp_replace (
i.data_record
, '(^|,)("[^"]*")+(,|$)' -- changed
, '\1\3' -- changed
)
, '(^|,)("[^"]*")+(,|$)' -- changed
, '\1\3' -- changed
)
, ','
)
Testcases
-- 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;