Първо елиминирайте ограниченото съдържание, пребройте след това:
regexp_count (
regexp_replace (
regexp_replace (
i.data_record
, '(^|,)"[^"]*"(,|$)'
, '\1\2'
)
, '(^|,)"[^"]*"(,|$)'
, '\1\2'
)
, ','
)
Влагането на regexp_replace
calls за съжаление е необходимо, за да се обработват правилно последователни полета, разделени с кавички:всяка разделителна запетая се консумира от модела на регулярен израз и по този начин няма да бъде взета под внимание за последващо съвпадение.
Regexen на Oracle не поддържа оператора look-head, който би бил естественият начин за справяне с тази ситуация.
Предвид удара на производителността на извикванията на regexp_... може би е по-добре да използвате
length(i.data_record) - length ( replace ( regexp_replace ( i.data_record, '(^|,)"[^"]*"(,|$)', '\1\2' ),',','' ) )
Предупреждение
Това решение не обработва dкавички в стойностите на полетата, които обикновено се представят като ""
или \"
.
Първият случай може да се третира елегантно:Вместо да се интерпретира ""
вътре в поле, разделено с кавички, разглеждайте цялото съдържание на полето като съпоставяне на 1 или повече низове, разделени с dquote, които не съдържат dquotes. Въпреки че не бихте следвали този маршрут при обработката на данните (всички кавички ще бъдат загубени), можете да използвате тази перспектива за целите на броенето:
regexp_count (
regexp_replace (
regexp_replace (
i.data_record
, '(^|,)("[^"]*")+(,|$)' -- changed
, '\1\3' -- changed
)
, '(^|,)("[^"]*")+(,|$)' -- changed
, '\1\3' -- changed
)
, ','
)
Тестови случаи
-- 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;