Hilangkan konten yang dibatasi terlebih dahulu, hitung setelahnya:
regexp_count (
regexp_replace (
regexp_replace (
i.data_record
, '(^|,)"[^"]*"(,|$)'
, '\1\2'
)
, '(^|,)"[^"]*"(,|$)'
, '\1\2'
)
, ','
)
Penyarangan regexp_replace
panggilan sayangnya diperlukan untuk menangani bidang yang dipisahkan kutipan secara berurutan dengan benar:koma pemisah apa pun dikonsumsi oleh pola regexp dan dengan demikian tidak akan diperhitungkan untuk kecocokan berikutnya.
Regexen Oracle tidak mendukung operator lookahead yang merupakan cara alami untuk menangani situasi ini.
Mengingat hit kinerja panggilan regexp_... Anda mungkin lebih baik menggunakan
length(i.data_record) - length ( replace ( regexp_replace ( i.data_record, '(^|,)"[^"]*"(,|$)', '\1\2' ),',','' ) )
Peringatan
Solusi ini tidak menangani dquotes dalam nilai bidang, yang biasanya direpresentasikan sebagai ""
atau \"
.
Kasus sebelumnya dapat ditangani dengan elegan:Alih-alih menafsirkan ""
di dalam bidang yang dipisahkan tanda kutip, pertimbangkan seluruh konten bidang sebagai penjajaran dari 1 atau lebih string yang dipisahkan tanda kutip yang tidak mengandung tanda kutip. Meskipun Anda tidak akan mengikuti rute ini dalam memproses data (semua dquote akan hilang), Anda dapat menggunakan perspektif ini demi menghitung:
regexp_count (
regexp_replace (
regexp_replace (
i.data_record
, '(^|,)("[^"]*")+(,|$)' -- changed
, '\1\3' -- changed
)
, '(^|,)("[^"]*")+(,|$)' -- changed
, '\1\3' -- changed
)
, ','
)
Kasus uji
-- 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;