0

示例数据:

1, test, "xy, yz", dog, cat
2, test2, xy, fish, bear

正如您在上面看到的,第二列可能会或可能不会用逗号括在引号中作为字符串的一部分。

我只是想找到一种方法来忽略引号中的逗号(如果有的话)。我正在使用 UTL_FILE 并且不能使用外部表,我知道我知道,但我不是能够做出决定的人。

我还没有真正“尝试”过任何东西,因为在这种特殊情况下我找不到任何可以尝试的东西。我有在每个逗号之间提取子字符串的代码,但显然,会将“xy,yz”拆分为 2 个单独的字符串。通过使用 " 作为该特定列的分隔符,我已经能够让它在 ONE 行上工作,但是当下一行没有第二列的引号时,这会很糟糕。

4

2 回答 2

3

如果您可以将输入文件的所有字段都用双引号括起来(或者可以在阅读后翻译它;我的正则表达式不够好),您可以使用dbms_utility.comma_to_table; 需要将字段括起来,因为(如此所述)标记必须是有效的对象名称,因此1会导致错误。例如:

declare
    file utl_file.file_type;
    list varchar2(120);
    tablen binary_integer;
    tab dbms_utility.lname_array;
begin
    file := utl_file.fopen('MY_DIR', 'test1.csv', 'R');
    loop
        begin
            utl_file.get_line(file => file, buffer => list);
        exception
            when no_data_found then
                exit;
        end;
        dbms_output.put_line('Raw list: ' || list);

        dbms_utility.comma_to_table(list => list,
            tablen => tablen, tab => tab);

        for i in 1..tablen
        loop
            dbms_output.put_line('Column ' || i || ': '
                || replace(tab(i), '"'));
        end loop;
    end loop;
    utl_file.fclose(file);
end;
/

给出:

Raw list: "1","test","xy, yz","dog","cat"
Column 1: 1
Column 2: test
Column 3: xy, yz
Column 4: dog
Column 5: cat
Raw list: "2","test2","xy","fish","bear"
Column 1: 2
Column 2: test2
Column 3: xy
Column 4: fish
Column 5: bear
Raw list: "3","test3","ab, cd","rabbit, rabbit","duck"
Column 1: 3
Column 2: test3
Column 3: ab, cd
Column 4: rabbit, rabbit
Column 5: duck

如果它们没有被引用,那么您可以使用正则表达式(来自此处的模式):

declare
    file utl_file.file_type;
    list varchar2(120);
    pattern varchar2(15) := '("[^"]*"|[^,]+)';
    c sys_refcursor;
    i number;
    f varchar2(20);
begin
    file := utl_file.fopen('MY_DIR', 'test2.csv', 'R');
    loop
        begin
            utl_file.get_line(file => file, buffer => list);
        exception
            when no_data_found then
                exit;
        end;

        dbms_output.put_line('Raw list: ' || list);

        open c for
             select level as col,
                 regexp_substr(list, pattern, 1, rownum) split  
             from dual
             connect by level <= length(regexp_replace(list, pattern))  + 1;

        loop
            fetch c into i, f;
            exit when c%notfound;
            dbms_output.put_line('Column ' || i || ': ' || replace(f, '"'));
        end loop;
        close c;

    end loop;
    utl_file.fclose(file);
end;
/

这使:

Raw list: 1,test,"xy, yz",dog,cat
Column 1: 1
Column 2: test
Column 3: xy, yz
Column 4: dog
Column 5: cat
Raw list: 2,test2,xy,fish,bear
Column 1: 2
Column 2: test2
Column 3: xy
Column 4: fish
Column 5: bear
Raw list: 3,test3,"ab, cd","rabbit, rabbit",duck
Column 1: 3
Column 2: test3
Column 3: ab, cd
Column 4: rabbit, rabbit
Column 5: duck

我不确定您是否真的在问题中显示的字段之间有空格。如果是这样,第一种方法仍然有效,您可以添加一个trim()around tab(i)。第二种方法失败了,所以需要一些调整......

于 2013-02-01T09:08:55.793 回答
0

Oracle SQL Developer 工具附带一个支持 CSV 的数据导入向导。查看手册的第 5.34 节。这可能比手动处理 csv 更容易。如果需要进行任何处理,您可以通过 excel/perl 进行。

于 2013-01-31T05:02:01.953 回答