MeWrite Docs

Duplicate entry 'x' for key 'PRIMARY'

MySQLで主キーやユニークキーの重複が発生した際のエラー

概要

MySQLで主キー(PRIMARY KEY)またはユニーク制約(UNIQUE)が設定されたカラムに、既に存在する値を挿入しようとした際に発生するエラーです。

エラーメッセージ

ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
ERROR 1062 (23000): Duplicate entry 'user@example.com' for key 'users.email_unique'

原因

  1. 主キーの重複: 既に存在するIDで挿入しようとしている
  2. ユニーク制約違反: メールアドレスなどのユニークカラムが重複
  3. AUTO_INCREMENTの問題: 手動でIDを指定してしまった
  4. データ移行時: 元データに重複があった
  5. 並行処理: 同時に同じデータを挿入しようとした

解決策

1. INSERT IGNOREを使用

1
2
3
-- 重複時は無視して続行
INSERT IGNORE INTO users (id, email, name)
VALUES (1, 'user@example.com', 'John');

2. ON DUPLICATE KEY UPDATEを使用

1
2
3
4
5
6
-- 重複時は更新
INSERT INTO users (id, email, name)
VALUES (1, 'user@example.com', 'John')
ON DUPLICATE KEY UPDATE
    name = VALUES(name),
    updated_at = NOW();

3. REPLACEを使用

1
2
3
-- 重複時は削除して挿入(トリガーに注意)
REPLACE INTO users (id, email, name)
VALUES (1, 'user@example.com', 'John');

4. 挿入前に存在確認

1
2
3
4
5
6
-- 存在しない場合のみ挿入
INSERT INTO users (email, name)
SELECT 'user@example.com', 'John'
WHERE NOT EXISTS (
    SELECT 1 FROM users WHERE email = 'user@example.com'
);

5. AUTO_INCREMENTをリセット

1
2
3
4
5
-- 最大値を確認
SELECT MAX(id) FROM users;

-- AUTO_INCREMENTをリセット
ALTER TABLE users AUTO_INCREMENT = 100;

6. Laravelでの対処

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// firstOrCreate: 存在すれば取得、なければ作成
$user = User::firstOrCreate(
    ['email' => 'user@example.com'],
    ['name' => 'John']
);

// updateOrCreate: 存在すれば更新、なければ作成
$user = User::updateOrCreate(
    ['email' => 'user@example.com'],
    ['name' => 'John Updated']
);

// upsert: 一括でupsert(Laravel 8+)
User::upsert([
    ['email' => 'user1@example.com', 'name' => 'User 1'],
    ['email' => 'user2@example.com', 'name' => 'User 2'],
], ['email'], ['name']);

7. トランザクションで対処

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
DB::transaction(function () {
    $exists = User::where('email', 'user@example.com')
        ->lockForUpdate()
        ->exists();

    if (!$exists) {
        User::create([
            'email' => 'user@example.com',
            'name' => 'John'
        ]);
    }
});

8. 重複データの調査

1
2
3
4
5
6
7
8
9
-- 重複しているデータを確認
SELECT email, COUNT(*) as count
FROM users
GROUP BY email
HAVING count > 1;

-- 重複を除いて挿入
INSERT INTO users_new (email, name)
SELECT DISTINCT email, name FROM users_old;

PHP/PDOでの例外処理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
try {
    $pdo->exec("INSERT INTO users (email) VALUES ('user@example.com')");
} catch (PDOException $e) {
    if ($e->getCode() == 23000) {
        // 重複エラー
        echo "Email already exists";
    } else {
        throw $e;
    }
}

よくある間違い

  • テスト環境でシーダーを何度も実行してIDが重複
  • CSVインポート時に重複チェックをしない
  • 複合ユニークキーの片方だけを考慮する

関連エラー

参考リンク

MySQL の他のエラー

最終更新: 2025-12-13