0

サンプルデータ:

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

上記のように、2 番目の列は文字列の一部としてコンマを使用して引用符で囲まれている場合と囲まれていない場合があります。

どちらかが存在する場合、引用符内のコンマを無視する方法を見つけようとしています。私は UTL_FILE を使用していて、外部テーブルを使用できません。私は知っていますが、決定を下すのは私ではありません。

この特定のシナリオで試すものを見つけることができなかったため、まだ何も「試していません」。各コンマ間の部分文字列を抽出するコードがありますが、明らかに、「xy、yz」を2つの別々の文字列に分割します。その特定の列の区切り文字として " を使用して、1 つの行で動作させることができましたが、次の行に 2 番目の列の引用符がない場合、それは地獄になります。

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)。2番目の方法は機能しないため、少し調整が必要です...

于 2013-02-01T09:08:55.793 に答える
0

Oracle SQL Developer ツールには、CSV をサポートするデータ インポート ウィザードが付属しています。マニュアルの § 5.34 を見てください。csv を手動で処理するよりもおそらく簡単です。処理が必要な場合は、Excel / Perl を使用して実行できます。

于 2013-01-31T05:02:01.953 に答える