繁体   English   中英

plsql中的csv文件中的逗号分隔字段

[英]Comma-delimited fields in a csv file in plsql

我有

   WHILE INSTR (l_buffer, ',', 1, l_col_no) != 0

它检查l_buffer是否用逗号分隔并进入循环。

现在我有一个带有值的文件

CandidateNumber,rnumber,title,OrganizationCode,OrganizationName,JobCode,JobName
10223,1600003B,Admin Officer,00000004,"Org Land, Inc.",ORGA03,ORGA03 HR & Admin

在此文件中,它正在考虑“ Org Land,Inc.”。 如因两个词,在两者之间。 有没有一种方法可以通过使用Instr或其他方法将其视为一体?

可怕的主意。 如果您被迫使用以字符分隔的字符串,那么您至少应该能够要求的是,分隔符是一个所有字符,但保证不会出现在常规字段值中。

您提出的问题可以解决。 我在下面展示了一个解决方案-可能接近最有效的解决方案,但至少遵循逻辑并不难。 我特意选择了一个示例(第五个字符串)来演示它如何失败。 我假设一对双引号(一个开始和一个结束)之间的任何逗号都应变为“不可见”-视为它们不是分隔符,而是字段值的一部分。 如果以不同于“常规”的方式使用双引号,则会中断-参见我的示例字符串#5。 它还会破坏逗号的任何其他“自然”使用(在这里,它们不是分隔符)-例如,如果您拥有一个值为$ 1,000.00的字段怎么办? 现在,您也需要“转义”该逗号。 可能至少还会再提出十种类似的情况-您是否要围绕所有这些情况进行编码?

现在,为了我自己的学习和实践,我假装只有在逗号之间用逗号隔开(以使令牌化过程不可见)的唯一方式是:将逗号括在开头和结尾的双引号之间(由排序:从字符串开头算起双数的双引号是一个开始的数字,而算术双数的双引号是一个结束的数字)。 这是解决方案; 在顶部测试字符串,包括一些用于测试对null的正确处理的字符串,以及紧随其后的输出。

祝好运!

with test_strings (r, s) as (
        select 1, 'abdc, ronfn 0003, "ABC, Inc.", 9939' from dual union all
        select 2, 'New Delhi'                           from dual union all
        select 3, null                                  from dual union all
        select 4, ','                                   from dual union all
        select 5, 'If needed, use double quote("), OK?' from dual
     ),
     t (r, s) as (
        select r, ',' || s || ',' from test_strings
     ),
     ct (r, nc, nq) as (
        select r, regexp_count(s, ','), regexp_count(s, '"') from t
     ),
     c (r, pos) as (
        select t.r, instr(t.s, ',', 1, level) from t join ct on t.r = ct.r 
        connect by level <= ct.nc and t.r = prior t.r and prior sys_guid() is not null
     ),
     q (r, pos) as (
        select t.r, instr(t.s, '"', 1, level) from t join ct on t.r = ct.r
        connect by level <= ct.nq and t.r = prior t.r and prior sys_guid() is not null
     ),
     p (r, pos_from, pos_to, rn) as (
        select r, pos, lead(pos) over (partition by r order by pos),
               row_number() over (partition by r order by pos) from c 
           where mod((select count(1) from q where q.r = c.r and q.pos != 0 
                                                             and q.pos < c.pos), 2) = 0
     )
select p.r as string_number, p.rn as token_number,
       substr(t.s, p.pos_from + 1, p.pos_to - p.pos_from - 1)
from t join p on t.r = p.r
where p.pos_to is not null
order by string_number, token_number
;

结果:

STRING_NUMBER TOKEN_NUMBER TOKEN
------------- ------------ --------------------
            1            1 abdc
            1            2  ronfn 0003
            1            3  "ABC, Inc."
            1            4  9939
            2            1 New Delhi
            3            1
            4            1
            4            2
            5            1 If needed

9 rows selected.

使用记事本++,并将所有逗号更改为“;”。 在此之前,您应该使用REGEXP更改双引号之间的所有逗号,例如“ @”。 然后ctrl+h >','到';' 并 ','。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM