MySQLの「ON DUPLICATE KEY UPDATE」とUPSERTを徹底解説!重複データへのスマートな対応術

こんにちは。ゆうせいです。
今回は、MySQLで非常によく使われる便利な構文、「ON DUPLICATE KEY UPDATE」と、いわゆるUPSERT(アップサート)について解説します。
「INSERTしようとしたら、すでに同じデータがあった!」
そんなとき、あなたならどうしますか?
手動で確認してからUPDATEしますか?それともエラーで止めますか?
実は、自動的に「追加 or 更新」をしてくれる構文があるんです。
これを理解すれば、データ処理の幅がぐっと広がりますよ!
そもそもUPSERT(アップサート)とは?
INSERT(追加)+ UPDATE(更新)=UPSERT
UPSERTとは、「Update if exists, Insert if not(存在すれば更新、なければ追加)」の略語です。
まるで、家に誰かがいれば荷物を渡し、いなければポストに入れていく宅配のような動きですね。
MySQLでは、このUPSERTをON DUPLICATE KEY UPDATE
構文を使って実現できます。
基本構文:ON DUPLICATE KEY UPDATE
INSERT INTO テーブル名 (カラム1, カラム2, ...)
VALUES (値1, 値2, ...)
ON DUPLICATE KEY UPDATE カラムX = 値X, カラムY = 値Y;
例1:IDが重複していたら更新
INSERT INTO employees (id, name, department)
VALUES (5, '佐藤 太郎', '営業')
ON DUPLICATE KEY UPDATE
name = '佐藤 太郎',
department = '営業';
この構文はこう読みます:
「ID=5がなければ新規追加、あれば
name
とdepartment
を上書きせよ!」
どのキーが重複を引き起こすのか?
対象は「PRIMARY KEY」または「UNIQUEキー」
たとえば、id
カラムが主キー(PRIMARY KEY)になっていれば、それが重複の判定基準になります。
また、email
などにUNIQUE
制約を付けていれば、そちらでも発動します。
CREATE TABLE users (
id INT PRIMARY KEY,
email VARCHAR(255) UNIQUE,
name VARCHAR(100)
);
このようなテーブルでは、idまたはemailが重複すればUPSERTが発動します。
特殊な値:VALUES()
関数の活用(MySQL 5系まで)
MySQL 5系では、VALUES(カラム名)
を使って、INSERTした値を再利用できます。
INSERT INTO products (id, name, price)
VALUES (1, 'みかん', 120)
ON DUPLICATE KEY UPDATE
price = VALUES(price);
このように書くと、「同じIDの商品があったら、価格だけを上書きする」ことができます。
ただし!MySQL 8.0以降ではこのVALUES()
は非推奨になりました。
代わりにAS new
でエイリアスを使う方法が主流です。
MySQL 8.0以降の書き方(エイリアス使用)
INSERT INTO products (id, name, price)
VALUES (1, 'りんご', 150) AS new
ON DUPLICATE KEY UPDATE
price = new.price;
この方法なら、将来的にも安心して使えますね!
UPSERTを使うときの注意点
UPDATEされるのは明示したカラムだけ
たとえば、以下のように書いたとしましょう:
ON DUPLICATE KEY UPDATE updated_at = NOW();
この場合、重複が起きてもupdated_at
しか更新されません。
ほかのカラムはそのままです。
副作用に注意
UPSERTは便利な反面、以下のような注意点があります:
注意点 | 内容 |
---|---|
トリガーが2回動く可能性あり | INSERT → UPDATEの順に発火 |
ログが煩雑になる | データベースログの可読性に影響 |
複雑なUPDATEだと遅くなる | 条件分岐が多い場合は分けた方が安全 |
UPSERTが特に便利なシーン
- ユーザーが初回アクセス時はINSERT、再ログイン時はUPDATE
- 外部システムから定期的に情報を取り込むとき
- 「存在チェック → 分岐してINSERTかUPDATE」する処理を1文で済ませたいとき
これらの処理がたった1行でスマートに書けるのは、本当に助かります!
DELETEとの組み合わせには注意!
UPSERTの真逆がDELETE
です。
「なければINSERT」ではなく「あるなら削除」するような処理は、UPSERTではなく別途制御ロジックを使いましょう。
今後の学習ステップ
UPSERTをマスターしたら、次に学ぶべき内容は次のとおりです:
- MERGE文(標準SQLに近い):MySQLにはまだ実装されていませんが、他のDBではよく使われます
- REPLACE INTO構文:既存レコードを削除→新規INSERT(ただし副作用が強い)
- トランザクションとロックの理解:複数のUPSERTが同時に走ったときの挙動を制御
また、「条件付きで一部だけ更新したい」といったニーズには、CASE文との組み合わせもおすすめです。
セイ・コンサルティング・グループの新人エンジニア研修のメニューへのリンク
投稿者プロフィール

- 代表取締役
-
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。