Database JUNKY

MySQL,MariaDBを中心としたブログです

改行を含むCSVファイルをインポートする方法

改行文字を含むCSVデータをテーブルにインポートする方法

DB2間のIMPORT&EXPORTであれば、IXFファイルで行うことで一発解決なのですが、色々なシステムが 絡んできますと、そういうわけにいかなくなります。なにが言いたいかというと、ORACLEから、DB2とか、 CSVファイルから、DB2へ・・。とかです。そんな数あるパターンからCSVファイルをDB2にインポートするケースが 非常に多いかと思いますので、今回は、csvファイルのインポートについて書いていこうかと思います。

db2へのインポートには、importコマンドと、loadコマンドがあります。importは、ファイルからデータを一行毎に読み出し、ターゲットに書き込む処理です。なので、すこしニュアンスが違いますが、1000件あったら、1000件分の トランザクションが発生します。一方のloadコマンドは、トランザクションを発生させないでダイレクトにデータを書き込むコマンドです。よって、importコマンドよりloadコマンドのほうが圧倒的に処理速度は速いですが、トランザクションログを 吐き出さない性質上、さまざまな諸問題も発生します。(ここではめんどくさいので割愛します) 今回は、importを例に説明します。

importコマンドについて

  1. 以下のコマンドでインポートを行います。 IMPORT FROM /work/data.csv OF DEL MODIFIED BY CODEPAGE=954 delprioritychar COMMITCOUNT 1000 INSERT_UPDATE INTO TARGET_TABLE

本ページは改行を含むCSVデータを・・というところが主題なので、その部分を説明しますと、インポートオプションで、delprioritychar を指定することで実現できます。単純に言いますと、改行文字をレコードの終わりと判断しないのですが、細かい話ですとこんな規則になります。

区切り文字の現在のデフォルト優先順位は、(1) レコード区切り文字、(2) 区切り文字、(3) 列区切り文字です。 この修飾子を使用すると、区切り文字の優先順位が (1) 区切り文字、(2) レコード区切り文字、(3) 列区切り文字に戻り、 以前の優先順位に依存している既存のアプリケーションが保護されます。構文は以下のとおりです。 db2 load ... modified by delprioritychar ... たとえば、以下のような DEL データ・ファイルがあるとします。 "Smith, Joshua",4000,34.98<row delimiter> "Vincent,<row delimiter>, is a manager", ... ... 4005,44.37<row delimiter> delprioritychar 修飾子が指定されている場合、このデータ・ファイルには 2 行しかありません。 2 番目の <row delimiter> は 2 番目の行の最初のデータ列の一部と解釈されますが、 1 番目と 3 番目の <row delimiter> は実レコードの区切り文字と解釈されます。 この修飾子が指定されて いない 場合、このデータ・ファイルでは 3 行になり、 各行は <row delimiter> によって区切られます。

どうですか?わかりますか?IBMのオンラインマニュアルを抜粋した部分になります。すごくむづかしく書いているように見えますが、ようは、レコードの終わり(行)の判断優先順位を 変えているだけのことです。

話は変わりますが・・・。ここはマニュアルに載っていない話です。

importコマンドの構文はこれでいいのですが、インポートするcsvファイルの文字コードは注意しないと結構はまります。(私ははまりました) たとえば、csvファイルは、windowsのsijis形式で、db2の環境が、linuxだった場合とかですね。csvファイルは、excel等で閲覧することに支障が出ないようsjis形式で保存する ことが多いのですが上記1の処理のようにオプションを指定しても(codepageとか、delpriorityとか)正常にインポートすることができないことが多いです。結局のところdb2コマンドで このケースで発生する問題を回避するオプションはありません。まず何でうまくいかないか? linux上のDB2では、どうも改行コードの解釈があまりよろしくないようなのです。 通常windows sjis系のテキスト改行文字コードは、CrLf(キャリッジリターン&ラインフィード)、一方のunix(linux)は、Lf(ラインフィード)です。 unix系での改行文字の判断は、このLfで行うため、CrLfをという改行コードは、改行と判断してくれないようなのです。単純な文字コードは、codepageで補正することはできますが、 この改行コードだけはどうもやってくれないらしいです。当該処理を、unix上で、データベースにインポートする場合は、nkfなどを利用して文字コード、改行コード変換をあらかじめ しておいたほうが得策のようです。私の場合は、nkfを利用することで問題が解決しました。以下のような感じで変換しちゃってください。(逆にwindowsは、lfをきっと、crlfにしないといけないと思う)

$ nkf -e -Lu text_sjis.csv > text_euc.csv