DB にレコードを INSERT
するとき、一手間加えて 未登録の場合に限って登録 や 登録済みなら一部フィールドだけ上書き などしたくなりますよね。
ここ最近、そのような SQL を書くことが多かったのでメモしておきます。
ちなみに MySQL の独自構文などもバリバリ使っているので、他のベンダーの DB に適用するときは部分的な書き換えが必要かもしれません。
レコードが存在していなかったら新規登録、存在していれば上書き
INSERT INTO `posts`( `id` ,`title` ,`body` ,`created_at` ,`updated_at` ) VALUES ( 42 ,'test title' ,'test body' ,'1970-01-01 00:00:00' ,'1970-01-01 00:00:00' ) ON DUPLICATE KEY UPDATE `title` = VALUES(`title`) ,`body` = VALUES(`body`) ,`updated_at` = VALUES(`updated_at`)
UNIQUE インデックスまたは PRIMARY KEY を重複させるようなレコードを INSERT
しようとしたときに、INSERT
ではなく UPDATE
が実行される。
その場合でも created_at
は上書きされない。
参考
レコードが存在していなかったら新規登録、存在していれば何もしない
INSERT INTO `tags` ( `id` ,`name` ) SELECT 42 ,'Technology' FROM dual WHERE NOT EXISTS ( SELECT `id` FROM `tags` WHERE `name` = 'Technology' )
タグ一覧テーブルからタグ名が ‘Technorogy’ であるものを探して、存在しなかった場合に限り INSERT
する。
8行目でテーブル名として使われている dual
は実際には参照されることのないダミーのテーブル名。