2011.11.16 しょーた
プライマリーキーや、ユニークキーが重複した際にUPDATEをかける、MySQLの便利な構文INSERT ON DUPLICATE KEY UPDATE。
これを使って一括更新(挿入)する方法を今更ながら知りましたので、メモ!
まず、こんなテーブルを作成。
CREATE TABLE `duplicate` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `value` varchar(255) NOT NULL, `update_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
で、適当にデータを入れておきます。
mysql> select * from duplicate; +----+-------+---------------------+ | id | value | update_at | +----+-------+---------------------+ | 1 | hoge | 0000-00-00 00:00:00 | | 2 | fuga | 0000-00-00 00:00:00 | | 3 | piyo | 0000-00-00 00:00:00 | +----+-------+---------------------+
ON DUPLICATE KEY UPDATEを使い一行ずつインサートする場合だと、こんな感じでUPDATEしたいカラムと値を指定してます。
INSERT INTO duplicate (id, value) VALUES (1, 'new-value') ON DUPLICATE KEY UPDATE value = 'new-value';
でもこれだと、複数行のインサート時に「どうやって値を設定すればいいのか...」と悩んでいました。
そこでドキュメントをよくよく見てみたところ、こんな書き方を発見!!
ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
実際に使ってみるとこんな感じです。
INSERT INTO `duplicate` (id, value) VALUES (1,'new-hoge'), (2, 'new-fuga'),(3,'new-piyo') ON DUPLICATE KEY UPDATE value=VALUES(`value`); mysql> select * from duplicate; +----+----------+---------------------+ | id | value | update_at | +----+----------+---------------------+ | 1 | new-hoge | 2011-11-08 05:21:25 | | 2 | new-fuga | 2011-11-08 05:21:25 | | 3 | new-piyo | 2011-11-08 05:21:25 | +----+----------+---------------------+
一括で更新でけた!!!
REPLACE INTOを使えば同じ様な事を実装できますが、REPLACE INTOだと新規挿入扱いになる為、ON UPDATE CURRENT_TIMESTAMPが使えません。。
それに、ON DUPLICATE KEY UPDATEなら、アプリケーションで利用する権限に削除権限を設定せずに済むので、何かと安心(?)。
ちゃんとドキュメントを読まないとなぁと思います。勉強します。