oracle標準添付の"DBMS_UTILITY.COMMA_TO_TABLE"は上手く動かなかったので、ネットから拾った方法で実施。

想定する状況

csvファイルを元データとして空テーブルにinsertする。

データとテーブルのカラム数や位置は同じで、csvファイルはダブルクォートやシングルクォートが除去されていると想定。


事前準備

[テーブル作成]

    idとnameの2カラムを持つテーブル"t_test"を作成

SQL> create table t_test
  2  (id number(10), name varchar2(10));


[テストデータ作成]

    id部分はシーケンスナンバー、name部分は乱数を使った文字列をセット。

  • 乱数出力用の関数

      ここから拾ったワンライナーを使って作成。※sayをprintに変更した

$ randstr() {
    len=$1
    perl -e 'BEGIN{ @chars = ("a".."z","A".."Z",0..9); $len = shift } { @rand_chars = map { $chars[sprintf("%d", rand(scalar(@chars)))] } 1..$len  } END{ print join("", @rand_chars) }' $len
}
  • ファイル出力
$ for i in {1..1000}; do _val=$(randstr 10); echo "$i,$_val" >> /tmp/input.csv; done
$ head /tmp/input.csv 
1,QcBtBbnIyW
2,RKaViH51BM
3,xQyyW2GNFd
4,blXFtJapLX
5,EmrfacYSy1
6,0qbl6tibOq
7,pVKkR0IMZ1
8,LqckQ5QbxX
9,ubaL9p4G5w
10,Xwtmzvru5V


[アクセス対象ディレクトリへの権限付与]

[Oracle] PL/SQL(その10: ユーティリティ・パッケージ(ファイル操作))を参照


インポート

[split関数を定義]

ここから持ってきたファンクション

構文
split(カンマ区切りの文字列, 取得したいフィールド, 区切り文字)
使用例
SQL> select split('AA,BBB,CCC',2,',') from dual;

[ファンクションの定義]

create or replace function split ( intext varchar2,
                                     itemno integer,
                                     delim varchar2)
return varchar2
is
myitem varchar2(255);
begin
    if intext is null or itemno is null or delim is null then
        return 'Invalid parameters !';
    end if;

    if itemno = 1 then
        myitem := SUBSTR( intext, 1, INSTR( intext || delim, delim, 1, 1 ) - 1 );
    else
        myitem := SUBSTR( intext, INSTR( intext, delim, 1, itemno-1 ) + 1,
        INSTR( intext || delim, delim, 1, itemno ) - INSTR( intext, delim, 1, itemno-1 ) - 1);
    end if;

    return myitem;
end;
/

[インポート処理]

declare
    dir_name  varchar2(30);
    file_name varchar2(20);
    fh        utl_file.file_type;
    read_line varchar2(1024);

    v_id      t_test.id%type;
    v_name    t_test.name%type;
    v_tmp varchar2(10);
begin
    dir_name  := 'UTL_DATA';
    file_name := 'input.csv';
    fh        := utl_file.fopen(dir_name, file_name, 'r');
    begin
        loop
            utl_file.get_line(fh, read_line);
            v_id   := split(read_line,1,',');
            v_name := split(read_line,2,',');
            --dbms_output.put_line(v_id||':'||v_name);
            insert into t_test (id, name) values (v_id, v_name);
        end loop;
        commit;
    exception
        when no_data_found then null;
    end;
    utl_file.fclose(fh);
end;
/

結果確認


SQL> select count(*) from t_test;

  COUNT(*)
----------
      1000