argius note

プログラミング関連

Oracle SQL*Loaderで関数と自動採番を使う

SQL*Loaderでデータをロードする際に、これまではCSV形式などをそのままロードする使い方だけでやっていました。

加工が必要な場合は、Perlなどで加工した後でロードしていました。でも、これだと無駄な1過程があるので、加工しながら直接ロードできるのではないか、ということでいくつか調べました。
詳細は参考URLを見ていただくのが早いですが、インデックスメモとして書いておきます。
実際に実行した環境のOracleバージョンは9iです。


サンプルとして、アクセスログのようなものを登録するデータベースを作ります。
まずはテーブル定義。

CREATE TABLE ACCESSLOG
(
  ACCESS_DATE CHAR(8),
  ACCESS_TIME CHAR(12),
  SEQ         NUMBER(10),
  LOGMESSAGE  VARCHAR(500),
  PRIMARY KEY (ACCESS_DATE,ACCESS_TIME,SEQ)
)


登録するデータは以下のようなフォーマットのCSVファイル"accesslog.csv"です。

DATE:20110208,09:28:24.422,MSGAAA
DATE:20110208,09:28:24.422,MSGAAA


制御ファイル(*.ctl)として、下記内容の"accesslog.ctl"を作ります。

LOAD DATA
APPEND INTO TABLE ACCESSLOG
FIELDS TERMINATED BY ','
TRAILING NULLCOLS
(
  ACCESS_DATE "SUBSTR(:ACCESS_DATE,-8,8)",
  ACCESS_TIME,
  SEQ SEQUENCE(MAX),
  LOGMESSAGE
)

関数の評価結果を登録する場合は、上記の"SUBSTR"のようにします。ここでは、"ACCESS_DATE"の先頭に余計な文字が含まれているので、後ろから数えて8バイト目から8バイトだけを登録するようにします。
"SEQ"は、"ACCESS_DATE"と"ACCESS_TIME"だけではUNIQUEにならないので、自動採番しています。"SEQUENCE(MAX)"を指定すると、そのフィールドの最大値を自動的に埋めてくれます。よって必然的にUNIQUEになります。


実行するには、次のようにします。

$ sqlldr user/passwd@sysname control='accesslog.ctl' data='accesslog.csv'
(メッセージ省略)
$ sqlplus user/passwd@sysname
(メッセージ省略)
> SELECT * FROM ACCESSLOG;
ACCESS_D ACCESS_TIME         SEQ LOGMESSAGE
-------- ------------ ---------- -----------------------------
20110208 09:28:24.422          1 MSGAAA
20110208 09:28:24.422          2 MSGAAA
>