- 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)
- Category
- Keys & Constraints
- Last reviewed
- 24 October 2026
On this page
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; 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 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; 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; 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 dataWhen 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 dataFor 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 dataMost 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 schemaFind 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
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;
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);
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);
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
- MySQL 8.0 server error message reference
- INSERT ... ON DUPLICATE KEY UPDATE statement
- INSERT statement (IGNORE modifier)
- AUTO_INCREMENT handling in InnoDB
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.