Skip to content
MySQL

MySQL Error 1062

Duplicate entry for key (PRIMARY KEY or UNIQUE index)

Applies to: MySQL 5.7, 8.0 and 8.4 (8.0 and later name the key as table.key)
Last technically reviewed 24 October 2026 on MySQL 8.0.46
The full message
ERROR 1062 (23000): Duplicate entry '1' for key 'customers.PRIMARY'
Other forms of this message
A UNIQUE index
ERROR 1062 (23000): Duplicate entry 'sara@example.com' for key 'customers.uq_customers_email'
Multi-column key (values joined with -)
ERROR 1062 (23000): Duplicate entry '10-1' for key 'order_lines.PRIMARY'
PHP PDO
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1' for key 'customers.PRIMARY'
INSERT IGNORE (a warning, the row is skipped)
Warning (Code 1062): Duplicate entry '1' for key 'customers.PRIMARY'
MySQL 5.7 (key name without the table)
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
Error number
1062
SQLSTATE
23000
Symbol
ER_DUP_ENTRY
Product
MySQL Server
Versions
MySQL 5.7, 8.0 and 8.4 (8.0 and later name the key as table.key)
Last reviewed
24 October 2026

What it means

Error 1062 means a row would store a value that already exists in a PRIMARY KEY or UNIQUE index, so MySQL rejected the statement.

A PRIMARY KEY or UNIQUE index allows each key value only once. When an INSERT, UPDATE, LOAD DATA or ALTER TABLE would create a second row with a value that is already there, InnoDB stops the statement and MySQL returns 1062. The message gives you the two things you need: the duplicate value ('1') and the key that rejected it (customers.PRIMARY, or the name of a UNIQUE index).

For a key over several columns, the values are joined with a hyphen, so '10-1' means order_id 10 and line_no 1. SQLSTATE 23000 is the standard class for integrity constraint violations; the same class is used for foreign key errors such as 1452, so check the error number, not just the SQLSTATE, in application code.

Common causes

  • The same row is inserted twice: a double-clicked submit button, a retried request or a re-run import script.
  • The application or an import file supplies key values itself (for example ids copied from another system) and one of them is already taken.
  • An UPDATE changes a key column, such as an email address with a UNIQUE index, to a value another row already has.
  • ALTER TABLE adds a UNIQUE index or PRIMARY KEY to a column that already holds duplicate values.
  • An INSERT ... SELECT or LOAD DATA brings in a source with duplicates, among its own rows or against rows already in the table.

Diagnose it

Read-only These statements only read metadata (information_schema, performance_schema and SHOW statements) or your own data. They do not change data, privileges or configuration, so they are safe to run first.

Which columns does the key cover?

Use the key name from the message (the part after the table name). PRIMARY is the primary key.

SELECT index_name, column_name, seq_in_index
FROM information_schema.statistics
WHERE table_schema = DATABASE()
  AND table_name = 'customers'
  AND non_unique = 0
ORDER BY index_name, seq_in_index;
What to look for

Every unique key on the table and its columns in order. A multi-column key is only duplicated when all of its columns match.

Find the row that already holds the value

SELECT *
FROM customers
WHERE id = 1;  -- the duplicate value from the message
What to look for

The existing row. Compare it with the data you were writing to decide whether to skip the new row, update the existing one or reject the request.

Find duplicates before adding a UNIQUE index or loading data

SELECT name, COUNT(*) AS copies
FROM customers
GROUP BY name
HAVING COUNT(*) > 1
ORDER BY copies DESC;
What to look for

Each value that appears more than once. Every row returned would make ALTER TABLE ... ADD UNIQUE fail with 1062 until the duplicates are resolved.

Check the AUTO_INCREMENT counter against the highest key

SHOW CREATE TABLE shows the next AUTO_INCREMENT value. Use it rather than information_schema.tables, whose AUTO_INCREMENT column can be cached and out of date.

SHOW CREATE TABLE customers;
SELECT MAX(id) AS highest_id FROM customers;
What to look for

If 1062 names an AUTO_INCREMENT column, the statement almost always supplied its own id. MySQL never hands out a value at or below the current maximum.

How to fix it

Each fix is labelled with what it changes. Try read-only checks and the least invasive fix first, and test changes outside production.

Update the existing row instead (upsert)

Changes data

When a matching key should update the row rather than fail, use INSERT ... ON DUPLICATE KEY UPDATE. The row alias (AS new) is available from MySQL 8.0.19; the older VALUES(name) form still works but is deprecated. If the table has more than one unique key, the update applies to whichever key matched first, so keep upserts to tables with one natural key.

INSERT INTO customers (id, email, name)
VALUES (1, 'sara@example.com', 'Sara')
AS new
ON DUPLICATE KEY UPDATE email = new.email, name = new.name;

Insert only the rows that are not there yet

Changes data

For re-runs and imports, insert just the missing keys. Keep the key in place even when the application checks first: two sessions can pass the check at the same moment, and only the unique index is reliable under concurrency.

Caution: INSERT IGNORE also skips duplicates, but it turns many other errors into warnings as well (for example invalid or truncated values), so bad data can be stored silently. Prefer the explicit NOT EXISTS form.

INSERT INTO customers (id, email, name)
SELECT s.id, s.email, s.name
FROM staging_customers AS s
WHERE NOT EXISTS (SELECT 1 FROM customers AS c WHERE c.id = s.id);

Let MySQL generate the key

Changes data

Most duplicate-id errors come from the application choosing ids. With an AUTO_INCREMENT key, leave the id out of the INSERT and read the new value with LAST_INSERT_ID().

INSERT INTO customers (email, name) VALUES ('ali@example.com', 'Ali');  -- no id supplied
SELECT LAST_INSERT_ID();

Resolve existing duplicates before adding a UNIQUE index

Changes schema

Find the duplicates with the read-only query above and agree with the data owner which row to keep (or merge them). Then add the index. On a large table, run the ALTER in a maintenance window: it rebuilds the index and can take a while.

ALTER TABLE customers ADD UNIQUE KEY uq_customers_name (name);

Examples

Inserting a duplicate primary key

CREATE TABLE customers (
    id    INT PRIMARY KEY,
    email VARCHAR(200),
    name  VARCHAR(100)
);

INSERT INTO customers (id, email, name) VALUES (1, 'sara@example.com', 'Sara');
INSERT INTO customers (id, email, name) VALUES (1, 'ali@example.com', 'Ali');  -- id 1 already exists
Result
ERROR 1062 (23000): Duplicate entry '1' for key 'customers.PRIMARY'

Reproduced on MySQL 8.0.46, 24 October 2026.

An UPDATE that copies a unique email address

CREATE TABLE customers (
    id    INT PRIMARY KEY,
    email VARCHAR(200),
    UNIQUE KEY uq_customers_email (email)
);
INSERT INTO customers VALUES (1, 'sara@example.com'), (2, 'ali@example.com');

UPDATE customers SET email = 'sara@example.com' WHERE id = 2;
Result
ERROR 1062 (23000): Duplicate entry 'sara@example.com' for key 'customers.uq_customers_email'

Reproduced on MySQL 8.0.46, 24 October 2026.

A duplicate in a multi-column key

CREATE TABLE order_lines (
    order_id INT,
    line_no  INT,
    PRIMARY KEY (order_id, line_no)
);

INSERT INTO order_lines (order_id, line_no) VALUES (10, 1), (10, 1);
Result
ERROR 1062 (23000): Duplicate entry '10-1' for key 'order_lines.PRIMARY'

Reproduced on MySQL 8.0.46, 24 October 2026.

Adding a UNIQUE index over existing duplicates

CREATE TABLE customers (id INT PRIMARY KEY, name VARCHAR(100));
INSERT INTO customers VALUES (1, 'Sara'), (2, 'Sara');

ALTER TABLE customers ADD UNIQUE KEY uq_name (name);
Result
ERROR 1062 (23000): Duplicate entry 'Sara' for key 'customers.uq_name'

Reproduced on MySQL 8.0.46, 24 October 2026.

How to prevent it

Let the database generate surrogate keys with AUTO_INCREMENT, and make writes that might run twice idempotent: an upsert for "create or update" actions, or INSERT ... SELECT ... WHERE NOT EXISTS for imports. De-duplicate staging data before loading it, and check for duplicates before adding a UNIQUE index.

Keep the unique index even when the application checks for duplicates, and handle error 1062 (not just SQLSTATE 23000) in your code so a duplicate becomes a clear message such as "this email is already registered" instead of a crash.

Common questions

How do I fix MySQL error 1062?

Read the duplicate value and the key name from the message, find the row that already holds that value, then decide: skip the new row, update the existing one with INSERT ... ON DUPLICATE KEY UPDATE, or stop sending ids and let AUTO_INCREMENT generate them.

Why do I get 1062 on an AUTO_INCREMENT column?

Because the statement supplied its own id. AUTO_INCREMENT only generates a value when the column is omitted or given NULL; an explicit id that already exists is rejected like any other duplicate.

Should I use INSERT IGNORE to get rid of error 1062?

Only with care. INSERT IGNORE skips duplicate rows, but it also downgrades other errors, such as invalid or out-of-range values, to warnings, so bad data can be stored without an error. An explicit NOT EXISTS check or an upsert is safer.

What does a value like '10-1' in the message mean?

The key covers more than one column. MySQL joins the values of all key columns with a hyphen, so '10-1' means the first key column is 10 and the second is 1.

Learn more on CodeWithSQL

Official documentation

Last technically reviewed 24 October 2026; examples and diagnostics run on MySQL 8.0.46. Message templates checked against the server's error catalogue (perror) for that version.

Still stuck on a MySQL error?

Browse the full MySQL error library, or get hands-on help from an experienced SQL professional.