MySQL で「Duplicate entry」が出て INSERT できない
Duplicate entry は PRIMARY KEY か UNIQUE 制約に同じ値を入れようとしたときのエラーである。
エラー文の末尾に出るキー名から、どの制約に当たったかを特定するのが先決。
重複を許すのか、更新に倒すのか、無視するのかで対処が変わる。
公開:
要約
ERROR 1062 (23000): Duplicate entry 'alice@example.com' for key 'users.email_unique' は、一意性制約に同じ値を入れようとしたときのエラーである。
読むべきは for key の後ろに出るキー名で、これがどの制約に当たったかを直接示している。
mysql> INSERT INTO users (email) VALUES ('alice@example.com');
ERROR 1062 (23000): Duplicate entry 'alice@example.com' for key 'users.email_unique'キー名が PRIMARY なら主キー、それ以外なら同名のユニークインデックスである。
まずここを確定させてから、重複をどう扱うかを決める。
よくある原因
- 単純な重複: すでにある値を入れようとしている。
アプリ側で存在チェックをしてから INSERT していても、チェックと INSERT の間に別のリクエストが入れば起きる。 - AUTO_INCREMENT のずれ:
idを明示して INSERT したり、ダンプを流し込んだりすると、次の採番値がテーブルの最大値より小さいままになる。
以降の INSERT が既存 id とぶつかる。 - 複合ユニークキーの見落とし:
UNIQUE (tenant_id, email)のような制約では、emailだけを見ても重複判定はできない。
組み合わせ全体で一意である必要がある。 - 照合順序による同一視:
utf8mb4_0900_ai_ciのような大文字小文字を区別しない照合順序では、Alice@example.comとalice@example.comは同じ値として扱われる。 - 二重実行: ジョブのリトライやリクエストの二重送信で、同じ行を 2 回入れている。
解決策
1. どのキーに当たったかを特定する
SHOW CREATE TABLE users\G出力の UNIQUE KEY / PRIMARY KEY の定義と、エラー文のキー名を突き合わせる。
複合キーなら構成列をすべて確認する。
2. 既存行の更新に倒す
INSERT INTO users (email, name) VALUES ('alice@example.com', 'Alice')
ON DUPLICATE KEY UPDATE name = VALUES(name);公式ドキュメント(新しいタブで開く) のとおり、PRIMARY KEY か UNIQUE インデックスの重複が起きたときに UPDATE へ切り替わる。
影響行数は新規挿入なら 1、更新なら 2 が返る。
3. 重複を捨ててよい場合
INSERT IGNORE INTO users (email) VALUES ('alice@example.com');IGNORE は重複エラーを警告に落として処理を続ける。
ただし重複以外のエラーも警告に変わるため、取り込みバッチのような用途に限定する。
4. AUTO_INCREMENT を実データに合わせる
SELECT MAX(id) FROM users;
ALTER TABLE users AUTO_INCREMENT = 1001;ダンプを取り込んだ直後に一度実行しておくと、以降の採番衝突を防げる。
5. 競合そのものを前提にする
存在チェックしてから INSERT する方式は競合状態を防げない。
一意性制約を残したまま、Duplicate entry を捕まえて「既に登録済み」として扱う実装にする方が安全である。