- MySQL
MySQL ERROR 1062 Duplicate entryの直し方
ERROR 1062 (23000): Duplicate entry 'sato@example.com' for key 'u1.uk_email' は、主キーまたは UNIQUE の列に、すでにある値と同じ値を入れようとしたときのエラーです。 エラー文の '...' が重複した値、for key '表.インデックス名' がどの制約かを表します。
| エラー文の key | 意味 | まず見ること |
|---|---|---|
'表.PRIMARY' |
主キーが重複 | ID を指定して入れていないか、AUTO_INCREMENT が上限に達していないか |
'表.uk_email' など |
UNIQUE のインデックスが重複 | 同じ値が本当にあるか、照合順序で「同じ」とみなされていないか |
確認環境:MySQL 8.0.46(既定の照合順序 utf8mb4_0900_ai_ci)、PyMySQL、MariaDB Connector/J 2.7.6(確認日 2026年10月11日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「MySQL ERROR 1062 Duplicate entryの直し方」
再現と、重複している行の確認
mysql> INSERT INTO u1 (email) VALUES ('sato@example.com');
ERROR 1062 (23000): Duplicate entry 'sato@example.com' for key 'u1.uk_email'
mysql> INSERT INTO u1 VALUES (1, 'x@example.com');
ERROR 1062 (23000): Duplicate entry '1' for key 'u1.PRIMARY'
SHOW INDEX FROM u1; -- uk_email がどの列か
SELECT * FROM u1 WHERE email = 'sato@example.com'; -- すでにある行
エラー文の値で検索すれば、ぶつかった行が見つかります。 ただし、次の「照合順序」の場合は、見た目が違う値でぶつかります。
落とし穴1:「ハハ」と「パパ」が重複になる(照合順序)
mysql> INSERT INTO u2 (name) VALUES ('ハハ');
Query OK, 1 row affected
mysql> INSERT INTO u2 (name) VALUES ('パパ');
ERROR 1062 (23000): Duplicate entry 'パパ' for key 'u2.uk_name'
mysql> INSERT INTO u2 (name) VALUES ('ハハ');
ERROR 1062 (23000): Duplicate entry 'ハハ' for key 'u2.uk_name'
MySQL 8.0 の既定の照合順序 utf8mb4_0900_ai_ci では、大文字小文字・濁点・半濁点・ひらがなとカタカナ・全角と半角を区別しません。 そのため、UNIQUE の列では「同じ値」と判定されました。
確認環境で、照合順序ごとに「同じ」と判定された組み合わせです。
| 照合順序 | 濁点(ハハ・パパ) | かな(ハハ・はは) | 全角半角(ハハ・ハハ) | 大小(abc・ABC) |
|---|---|---|---|---|
utf8mb4_0900_ai_ci(既定) |
同じ | 同じ | 同じ | 同じ |
utf8mb4_unicode_ci |
同じ | 同じ | 同じ | 同じ |
utf8mb4_general_ci |
別 | 別 | 別 | 同じ |
utf8mb4_ja_0900_as_cs |
別 | 同じ | 同じ | 別 |
utf8mb4_ja_0900_as_cs_ks |
別 | 別 | 同じ | 別 |
utf8mb4_bin・utf8mb4_0900_bin |
別 | 別 | 別 | 別 |
既定の照合順序では、ほかにも 「ゃ」と「や」(小さい文字)、「ABC」と「abc」が同じと判定されました。
名前・商品名・コードなど、1文字の違いを区別したい列は、照合順序を変えます。
ALTER TABLE u2 MODIFY name varchar(20) COLLATE utf8mb4_ja_0900_as_cs_ks; -- ひらがなとカタカナも区別
ALTER TABLE u2 MODIFY name varchar(20) COLLATE utf8mb4_0900_bin; -- すべて区別(バイナリ)
utf8mb4_ja_0900_as_cs_ks にすると「パパ」「はは」は入りましたが、半角の「ハハ」は、まだ「ハハ」と同じでした(全角と半角は区別しない)。完全に区別するなら utf8mb4_0900_bin です。照合順序は検索(WHERE name = 'はは')の結果も変えるので、変える前に影響を確かめます。照合順序の全体は、関連記事の「MySQL照合順序(collation)の違い|utf8mb4全種の比較表と選び方」で比べています。
末尾の空白
| 照合順序 | 'a' と 'a ' |
|---|---|
utf8mb4_0900_ai_ci・utf8mb4_0900_bin(NO PAD) |
別(末尾の空白も文字として比べる) |
utf8mb4_general_ci・utf8mb4_bin(PAD SPACE) |
同じ(重複になる) |
'sato@example.com '(末尾に空白)は、既定の照合順序では重複にならずに入りました。CSV から取り込んだ値に空白が混ざると、見た目が同じ行が2つできます。取り込む前に TRIM します。
落とし穴2:AUTO_INCREMENT が上限に達すると 1062
(TINYINT の AUTO_INCREMENT で、126 まで入っている)
mysql> INSERT INTO ai7(v) VALUES (1); -- 127 が入る
mysql> INSERT INTO ai7(v) VALUES (2);
ERROR 1062 (23000): Duplicate entry '127' for key 'ai7.PRIMARY'
型の上限に達すると、次の番号を作れず、上限の値をもう一度使おうとして 1062 になりました。 INT(符号あり)でも、2147483647 で同じエラーになりました。主キーの重複なのに、ID を指定していないときは、これを疑います。
SHOW TABLE STATUS LIKE 'ai7'; -- Auto_increment の値と、列の型の上限を比べる
| 型 | 上限(符号あり) | 直し方 |
|---|---|---|
| TINYINT | 127 | 型を大きくする |
| INT | 2,147,483,647 | BIGINT に変える(ALTER TABLE ... MODIFY id BIGINT AUTO_INCREMENT) |
失敗した INSERT も番号を消費します。 確認環境でも、重複で2回失敗したあとの次の行は、ID が 2 ではなく 4 になりました。番号が飛ぶのは異常ではありません。
落とし穴3:複数行の INSERT は、1行の重複で全部入らない
mysql> INSERT INTO m1 VALUES (2),(3),(1),(4); -- 1 がすでにある
ERROR 1062 (23000): Duplicate entry '1' for key 'm1.PRIMARY'
mysql> SELECT * FROM m1;
1 -- 2・3・4 も入っていない
InnoDB では、1つの INSERT 文の途中で失敗すると、その文の全部が取り消されました。 大量に入れるときは、先に重複を除くか、下の ON DUPLICATE KEY UPDATE を使います。
直し方:重複したときにどうしたいかで選ぶ
| したいこと | 書き方 | 注意 |
|---|---|---|
| あれば更新、無ければ追加 | INSERT ... AS new ON DUPLICATE KEY UPDATE |
主キーが変わらない(おすすめ) |
| あれば何もしない | INSERT ... ON DUPLICATE KEY UPDATE id = id |
重複以外のエラーは、エラーのまま |
| 置き換える | REPLACE INTO |
行を消して入れ直す。ID が変わり、子の行が消えることがある |
| 重複を無視 | INSERT IGNORE |
重複以外のエラーも消える(下で説明) |
ON DUPLICATE KEY UPDATE
INSERT INTO pa9 (code, name) VALUES ('C1', '佐藤2') AS new
ON DUPLICATE KEY UPDATE name = new.name;
| 結果 | 影響を受けた行数(ROW_COUNT()) |
|---|---|
| 新しく追加した | 1 |
| 既存の行を更新した | 2 |
| 既存の行と同じ値だった | 0 |
確認環境の結果も、公式マニュアルのとおり 1・2・0 でした。AS new の書き方は MySQL 8.0.19 以降で、それ以前の VALUES(name) の書き方は 8.0.20 から非推奨とされています。PostgreSQL の書き方との比較は、関連記事の「SQL UPSERTの書き方|PostgreSQL・MySQL・MERGE構文比較表」で扱っています。
REPLACE は、子の行を消すことがある
(pa9 の id=1 を、子のテーブル ch9 が ON DELETE CASCADE で参照している)
mysql> REPLACE INTO pa9 (code, name) VALUES ('C1', '佐藤2');
ROW_COUNT() = 2 -- 1行消して、1行追加
mysql> SELECT * FROM pa9;
2 C1 佐藤2 -- id が 1 から 2 に変わった
mysql> SELECT COUNT(*) FROM ch9;
0 -- 子の行が消えた
REPLACE は「更新」ではなく「削除して追加」でした。 外部キーに ON DELETE CASCADE があると、子の行も消えます。同じ操作を ON DUPLICATE KEY UPDATE で行うと、id は 1 のままで、子の行も残りました。
INSERT IGNORE は、重複以外のエラーも黙らせる
mysql> INSERT IGNORE INTO ig VALUES (1,'dup',9), (2,NULL,2), (3,'toolongname',3), (4,'ok','abc');
mysql> SHOW WARNINGS;
Warning 1062 Duplicate entry '1' for key 'ig.PRIMARY'
Warning 1048 Column 'name' cannot be null
Warning 1265 Data truncated for column 'name' at row 3
Warning 1366 Incorrect integer value: 'abc' for column 'qty' at row 4
| 入れた値 | 実際に入った値 |
|---|---|
name = NULL(NOT NULL の列) |
空文字 |
name = 'toolongname'(varchar(5)) |
'toolo'(切り捨て) |
qty = 'abc' |
0 |
IGNORE は重複だけでなく、NOT NULL・長さ・型のエラーも警告に変え、近い値に直して入れました(公式マニュアルでも同じ説明)。重複を無視したいだけなら、ON DUPLICATE KEY UPDATE id = id のほうが安全です。
UNIQUE を後から付けるとき:重複している行を探す
mysql> ALTER TABLE cu ADD UNIQUE KEY uk_email (email);
ERROR 1062 (23000): Duplicate entry 'a@x.jp' for key 'cu.uk_email'
SELECT email, COUNT(*) AS cnt, GROUP_CONCAT(id ORDER BY id) AS ids
FROM cu
GROUP BY email
HAVING COUNT(*) > 1;
email cnt ids
a@x.jp 2 1,3 ← id=3 は 'A@x.jp'(大文字小文字を区別しないので同じ)
b@x.jp 2 2,5
GROUP BY も列の照合順序で比べるので、UNIQUE で重複になる組み合わせが、そのまま見つかりました。 どちらを残すかを決めて消してから、UNIQUE を付けます。1件だけ残して消す SQL は、関連記事の「SQLで重複データを抽出・削除する方法|1件だけ残す書き方」で扱っています。
アプリから見たときの例外
| 言語・ドライバー | 例外(確認環境) |
|---|---|
| Python(PyMySQL) | pymysql.err.IntegrityError (1062, "Duplicate entry ...") |
| Java(JDBC) | java.sql.SQLIntegrityConstraintViolationException(errorCode=1062、SQLState=23000) |
「存在チェックしてから INSERT」でも 1062 になる
接続A:SELECT COUNT(*) ... WHERE email='new@example.com' → 0
接続B:SELECT COUNT(*) ... WHERE email='new@example.com' → 0
接続A:INSERT → 成功
接続B:INSERT → IntegrityError (1062, "Duplicate entry 'new@example.com' ...")
同時に2つの処理が「無い」と確認し、両方が INSERT すると、あとの方が 1062 になりました。 事前のチェックでは防げないので、UNIQUE 制約に任せて、1062 を受け取ったら「すでに登録済み」と扱うのが確実です。
確認の手順(チェックリスト)
| 順番 | 確認すること | 方法 |
|---|---|---|
| 1 | どの制約か | エラー文の for key '表.インデックス名' |
| 2 | ぶつかった行 | エラー文の値で SELECT |
| 3 | 見た目が違う値なのに重複 | 照合順序(SHOW FULL COLUMNS FROM 表) |
| 4 | 主キーで、ID を指定していない | AUTO_INCREMENT の上限(SHOW TABLE STATUS) |
| 5 | どうしたいか | 更新なら ON DUPLICATE KEY UPDATE。REPLACE・IGNORE は副作用に注意 |
| 6 | UNIQUE を後から付ける | GROUP BY ... HAVING COUNT(*) > 1 で探す |
よくある質問
Q. SQLSTATE は何ですか。
A. 23000(整合性制約の違反)です。外部キーのエラー(1452)と同じ SQLSTATE なので、区別するときはエラー番号(1062)を見ます。
Q. AUTO_INCREMENT の値を戻せば直りますか。 A. 手で大きな ID を入れたあとなどで、番号がずれている場合は直ります。上限に達している場合は、型を大きくしないと直りません。AUTO_INCREMENT の確認と変更は、関連記事の「MySQL AUTO_INCREMENTのリセット・確認・変更方法【コピペ用SQL】」で扱っています。
まとめ
- 主キー・UNIQUE に同じ値を入れたエラー。
for keyで制約、'...'で値が分かる - 既定の照合順序では、ハハ=パパ=はは=ハハ、abc=ABC。区別したい列は照合順序を変える
- AUTO_INCREMENT が型の上限に達すると、主キーの 1062 になる
- 複数行の INSERT は、1行の重複で全部取り消される
- 更新なら
ON DUPLICATE KEY UPDATE。REPLACEは削除と追加、IGNOREは別のエラーも消す - 事前のチェックでは同時の登録を防げない。UNIQUE と 1062 の処理で防ぐ
参考・出典
確認日はいずれも 2026年10月11日です。
- MySQL 8.0 Reference Manual「INSERT ... ON DUPLICATE KEY UPDATE Statement」:https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html
- MySQL 8.0 Reference Manual「INSERT Statement」:https://dev.mysql.com/doc/refman/8.0/en/insert.html
- MySQL 8.0 Reference Manual「Unicode Character Sets」:https://dev.mysql.com/doc/refman/8.0/en/charset-unicode-sets.html
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「MySQL ERROR 1062 Duplicate entryの直し方」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。