読者です 読者をやめる 読者になる 読者になる

SQL*LoaderでCSVを読み込みたいんです 追記

oracle db

SQL*LoaderでCSVを読み込みたいんです - なんでや。。
この愚かな記事に愚かな追記を。。

PRESERVE BLANKSで空白保持しても、DECIMAL EXTERNALやDATEのカラム(たぶんZONEDも)は勝手に空白トリムしてからうまくキャストしてロードしてくれる。CHARのカラムは空白保持したまま。

フィールドリストを以下のように書いたとする。

        EMPLOYEE_ID     DECIMAL EXTERNAL(6) ":EMPLOYEE_ID + 1",
        START_DATE      DATE 'FMYYYY/MM/DD',
        END_DATE        CONST '2012/03/04',
        JOB_ID          CHAR(10),
        DEPARTMENT_ID   POSITION(2) DECIMAL EXTERNAL(4)

試していないが、読み込んだCSVに対して以下のように挙動すると思われる。

  1. CSV1~2列目をEMPLOYEE_ID, START_DATEへマッピング。
    EMPLOYEE_IDはCSVの値にプラス1される。演算したい場合はこのようにダブルクオートで括って書く。確かINSERT文に書ける書き方なら何でもOKとかどこかに書いてあった気がする。
  2. END_DATEはCONSTANTなのでCSVからは読み込まない。書いてある通り2012/3/4がマッピングされる。
    またCONSTANTだからか演算結果をマッピングさせることはできない。
  3. CSV3列目をJOB_IDへマッピング。
  4. CSV2文字目(POSITION(2))から次のデリミタの手前までをDEPARTMENT_IDへマッピング。

読み込んだファイルのレコード先頭から末尾に向かってデリミタが来るまで読み込んで順番にフィールドにマッピングするのが原則と思われる。
POSITIONを指定することで無理矢理マッピングすることも可能だが、可変長レコードの場合はPOSITION(1)としか書けないはず。
CONSTANT指定したフィールドについてはファイルを読み進まないでくれるが、それ以外は必ず読み込むので、例えSTART_DATE DATE "SYSDATE"などと書いてあってもCSVはそのフィールドの分読み進まれる。

上記のようなフィールドリストなら、このようなCSVに対して

123,1999/12/31,IT_PROG

このようにINSERTされる(はず)。

123, 1999/12/31, 2012/03/04, IT_PROG, 23

おそらくこのように挙動するため、各カラムにランダムにマッピングしたいと思っても無理。
できるのは演算不可なCONSTANT値を指定することと、

HOGE "SYSDATE",
PIYO "1024 * 1024",
FUGA POSITION(1) DECIMAL EXTERNAL,
FOO CHAR,
BAR CHAR

みたいに途中で1文字目からポジションを指定し直すことくらい。
もうちょっとやり用はあるかも知れないけど、それくらい融通が利かない。

ちなみにCSV中のいらん列をFILLERという仮想カラムに対してマッピングすることで無視することが出来る。

ちょっとまとまりなくて読みにくいかも。。

参考

SQL*Loader制御ファイル・リファレンス