初投稿
できるエンジニアは良質なアウトプットをしてるな~と感じたので、僭越ながら投稿させていただきます。
やりたいこと
CSVファイルをテーブルに一括で取り込む際に、PRIMARY KEYまたはUNIQUEな値がすでに存在していたら、更新処理を行い、なければ登録処理を行う。
(ちなみにバージョンはPHP5.6、MySQL5.6)
実現方法
◆PDOのfetch使って一件一件ゴリゴリやる?
まず最初に思いついたのがこれ。
ループさせながら、一行とっては「ON DUPLICATE KEY UPDATE」構文を使って登録/更新していく。
う~ん、データ量が小さければいいけど、多くなると遅いなー。もっと効率よくできないものか。
◆「LOAD DATA INFILE」 構文という便利なものがあった!
参考1 参考2
リファレンスマニュアルによると、「INSERT ステートメントを多数使用する場合と比較して、20 倍速度が上がる。」らしい。
これはすごい。あれ、でもこれって登録処理できても更新処理できなくない?
◆「REPLACE」 構文を使えばできそう?
参考3
あ、なんだ、「LOAD DATA INFILE」の中に「REPLACE」指定すれば、PRIMARY KEYまたはUNIQUEな値がテーブルに存在していなければ登録、存在していれば更し、、、あれ、更新じゃなくてDELETEしてINSERTされるっぽいぞ!!!
これでは更新処理で更新したくない値(データの新規登録日など)も更新されてしまう、、
◆構文を組み合わせてなんとか実現できた!
ちょっと面倒だが、以下の手順を踏めば、「やりたいこと」が満たせた。
- 一時的に取り込み用のテーブルを用意する
CREATE TABLE tmp_table LIKE main_table;
→一時的に取り込むテーブルがすでに用意されている場合は、中身を消しておく
TRUNCATE TABLE tmp_table;
- 一時的に取り込むテーブルに「LOAD DATA INFILE」して取り込む
LOAD DATA INFILE 'file.csv' INTO TABLE tmp_table FIELDS TERMINATED BY ',' ;
- 取り込みたいテーブルに「ON DUPLICATE KEY UPDATE」して取り込む
INSERT INTO main_table SELECT * FROM tmp_table ON DUPLICATE KEY UPDATE main_field1 = VALUES(field1), main_field2 = VALUES(field2);
◆おわりに
最後まで読んでくださり有難うございました。
内容に不備などありましたら、ご指導お願いします。
それでは、またなんか内容見つけて投稿しよ~
さようなら~