sql >> データベース >  >> RDS >> Oracle

CSVOracleストアドプロシージャUTL_FILEを読み取るときに引用符の間のコンマを無視する

    すべてのフィールドを二重引用符で囲んで配信された入力ファイルを取得できる場合(または読み取り後に翻訳できます。私の正規表現では不十分です)、 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()を追加できます。 tab(i)周辺 。 2番目の方法は機能しないため、少し調整する必要があります...



    1. MySQL –現在のユーザーを知るためのさまざまな方法

    2. cakephpは古いデータ値+新しい値から更新データを保存します

    3. ORA-24247:ネットワーク・アクセスがアクセス制御リスト(ACL)によって拒否されました

    4. Oracle、Blobデータがエクスポートファイルにありません