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

时间:2016-05-28 19:08:44

标签: sql oracle 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或其他任何方式将其视为一个?

2 个答案:

答案 0 :(得分:1)

可怕的主意。如果你被迫使用以字符分隔的字符串,那么你应该要求的最少的是分隔符是一个完全保证的字符出现在常规字段值中。

你提出的问题可以解决。我在下面展示了一个解决方案 - 可能并不接近最有效,但至少应该不难遵循逻辑。我故意选择一个例子(第五个字符串)来演示它如何失败。我假设一对双引号(一个开头的和一个结束的)之间的任何逗号应该变得“不可见” - 被视为它们不是分隔符,而是字段值的一部分。如果以与“通常”不同的方式使用双引号,则会中断 - 请参阅我的示例字符串#5。它也会打破逗号的任何其他“自然”用法(它们不是分隔符) - 例如,如果你有一个价值$ 1,000.00的字段怎么办?现在你需要“逃避”这个逗号。有人可能会提出至少十种类似的情况 - 你打算围绕所有情况进行编码吗?

现在,对于我自己的学习和实践,我假装一个逗号可能需要“转义”(对于标记化过程变得不可见)的唯一方式是它是否包含在开头和结束双引号之间(简单地通过排序来确定:从字符串开头用奇数计数的双引号是开头的,带有偶数的双引号是结束的。这是解决方案;在顶部测试字符串,包括一些测试空值的正确处理,以及紧随其后的输出。

祝你好运!

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.

答案 1 :(得分:0)

使用记事本++,并将所有逗号更改为&#39;;&#39;。在它之前,您应该使用REGEXP来更改双引号之间的所有逗号,以便让我们说&#39; @&#39;。然后ctrl+h - &gt; &#39;,&#39;到&#39;;&#39;和&#39; @&#39;到&#39;,&#39;。