Nejprve odstraňte ohraničený obsah a poté počítejte:
regexp_count (
regexp_replace (
regexp_replace (
i.data_record
, '(^|,)"[^"]*"(,|$)'
, '\1\2'
)
, '(^|,)"[^"]*"(,|$)'
, '\1\2'
)
, ','
)
Vnoření regexp_replace
volání je bohužel nezbytné pro správné zpracování po sobě jdoucích polí oddělených uvozovkami:jakákoliv oddělovací čárka je spotřebována vzorem regulárních výrazů, a proto nebude při následné shodě brána v úvahu.
Regexeny Oracle nepodporují dopředný operátor, což by byl přirozený způsob řešení této situace.
Vzhledem k výkonu volání regexp_... by možná bylo lepší použít
length(i.data_record) - length ( replace ( regexp_replace ( i.data_record, '(^|,)"[^"]*"(,|$)', '\1\2' ),',','' ) )
Upozornění
Toto řešení nezpracovává dquotes v rámci hodnot polí, které jsou obvykle reprezentovány jako ""
nebo \"
.
První případ lze vyřešit elegantně:Místo interpretace ""
uvnitř pole s uvozovkami považujte obsah celého pole vedle sebe 1 nebo více řetězců oddělených dquote, které neobsahují dquote. I když byste se při zpracování dat neřídili touto cestou (všechny dquotes by byly ztraceny), můžete použít tuto perspektivu kvůli počítání:
regexp_count (
regexp_replace (
regexp_replace (
i.data_record
, '(^|,)("[^"]*")+(,|$)' -- changed
, '\1\3' -- changed
)
, '(^|,)("[^"]*")+(,|$)' -- changed
, '\1\3' -- changed
)
, ','
)
Testovací případy
-- 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;