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期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?