はじめに
OracleDBにXMLデータを列として持つテーブルを作成したい、そしてその列をいちいち手で追加するのは大変だからSQL*Loaderなるものを使って楽をしたい。
しかし、公式DocにあるSQL*LoaderのXML文書のロードのページが分かってる人向けすぎて何が何やら分からず大変困ってしまいました。
そのため次回混乱しないようにメモを残します。
テーブル構成・ファイル等
作りたいテーブルの形
以下のように通し番号、フォルダ名、中身を持つテーブル(DATATABLE)を作ります。
ID(通し番号) | foldername | data(XMLデータ) |
---|---|---|
1 | AAAAAAAA | <Data>...</Data> |
2 | BBBBBBBB | <Data>...</Data> |
... | ... | ... |
SQL文は以とします。
CREATE TABLE DATATABLE
(
ID number NOT NULL,
foldername char(9) NOT NULL,
data xmltype,
PRIMARY KEY (ID)
);
DATファイルの用意
公式ページのDocに従い、読み込みたいXMLファイルの一覧をDATファイルとして用意します。
AAAAAAAA/data.xml
BBBBBBBB/data.xml
...
このようにフォルダ以下のXMLファイルの名称は同じなので、テーブルではフォルダ名称だけを使いたいわけです。
ctlファイル
上記を実現するctlファイルはこうです。
LOAD DATA CHARACTERSET AL32UTF8
INFILE 'filelist.dat'
BADFILE 'failedRecord.csv'
APPEND
INTO TABLE DATATABLE
(
ID SEQUENCE( MAX ),
foldername position(1:8) char,
filename filler position(1:18),
data lobfile(filename) terminated by eof
)
XMLデータに日本語が含まれるため文字コードをAL32UTF8に指定しています。
これにより「filelist.dat」の中身を一行ずつ読み込み、DATATABLEに入れていきます。
・ID SEQUENCE( MAX ),
通し番号の指定です。ここはfilelist.datの中身には関係ありません。
・foldername position(1:8) char,
foldername列に、今読んでいる行の1文字目~8文字目を使えという指定です。
・filename filler position(1:18),
XMLデータ本体を読み込むためにはfoldernameだけだと駄目なので、一行丸々使いたい、だけど一行丸々のデータはテーブルには要らない…ということで「filler」として、このfilenameという変数はテーブルには入れないよという宣言をします。
position(1:18)と改めて頭から指定してフルパスを取得します。
一行丸々なのでそのままchar(18)としようとすると「/data.xml」部分だけになってしまいます。
・data lobfile(filename) terminated by eof
data列にfilenameを読み込みます。
これを
sqlldr userid=***/***@**.***.***.***:1521/*** control=load_data.ctl
として実行すれば完了です。
もっとスマートなctl文の書き方もあるとは思いますが、一応これで想定通りです。
詰まっていた点
はじめ、公式Docのctlにあるxmltype(XMLDATA)
を信じてxmltype(data)
と書いたらSQL*Loader-588
というエラーが出るうえに、このエラーをググってもエラーコード詳細が出てきませんでした。
SQL*Loader-00588
でググればいいということに中々思い至らず大変困っておりました。
このエラーを読むと「このテーブルはXML型ではない」とあるので、今回のように色々な型を使いたい場合は使えない指定のようでした。