はじめに
CSVファイルを1件1件取り出して、加工してSQLを生成……
なんてことを、これまでしてきました。
もちろんすごく遅いです。
LOAD DATA INFILEを使うことでファイルインポートができます。
とはいえ、ざっくり調べても「あまり使えなさそう?」と思っていた私がいます。
ですが理解してみると一転して、様々なCSV案件で大活躍です。
未来の私のために今日もメモします。
LOAD DATA INFILEとは
LOAD DATA INFILE ステートメントは、非常に高速にテキストファイルからテーブルに行を読み取ります。
参考URL
理解のポイント(下記構文を見ながら)
- CSVファイルを読み込み、INSERTを行うイメージです。
- CSVの1列目(例:A1,B1など)が、
users.id
カラムに入ります。 - CSVの2列目(例:A2,B2など)が、
users.name
カラムに入ります。- つまりカラムとCSVの順番は、バラバラでも対応が可能ということです
- SET以降は「CSVにはないけれどカラムに入れたい値」をセットすることができます。
- もはやCSVデータとはほぼ関係なく、SQL側のための機能です
構文
LOAD DATA INFILE 'nzn.csv'
INTO TABLE `users`
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES
(
`id`
, `name`
, `price`
) SET
`created_at` = TIMESTAMP
各行の理解
-
FIELDS TERMINATED
: CSVの区切り文字を指します。ほぼ必須です。 -
ENCLOSED BY '"'
: 文字列などはダブルクォーテーションで囲われていますが、良きように消してINSERTをしてくれます。ほぼ必須です。 -
LINES TERMINATED BY '\r\n'
: 改行コードの認識を定義します。- csvファイルがCRLFなのに
\n
と指定すると、1行しか入らないなど不都合が起きます。
- csvファイルがCRLFなのに
-
IGNORE 1 LINES
: CSVには見出しがつきもの。プログラム側で削除するより高速なのでLOAD DATA側で除外すると少し幸せになります。
ではbashから呼び出してみよう
readonly ENC='\"'; #エスケープ
$code="
LOAD DATA INFILE 'nzn.csv'
INTO TABLE users
FIELDS TERMINATED BY ','
ENCLOSED BY '${ENC}'
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES
(
id
, name
, price
) SET
created_at = TIMESTAMP
updated_at = ${TIME_STAMP}
";
ちなみにbashで実行の場合、バッククォーツ自体に意味があるので、誤認されるみたいです。
テーブルやカラムにも、バッククォーツは付けずに記述しましゅ。
最後に
他にも変数の指定ができますが、これが初めて使うときに理解を遠ざける要因の1つでした。結局、私の案件の場合は変数は不要でしたので、上記のようなLOAD DATAで落ち着きました。