Skip to content
MySQL

MySQL Error 1451

Cannot delete or update a parent row: a foreign key constraint fails

Applies to: MySQL 5.7, 8.0 and 8.4 (InnoDB tables with FOREIGN KEY constraints)
Last technically reviewed 24 October 2026 on MySQL 8.0.46
The full message
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`shop`.`orders`, CONSTRAINT `fk_orders_customer` FOREIGN KEY (`customer_id`) REFERENCES `customers` (`id`))
Other forms of this message
PHP PDO
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`shop`.`orders`, CONSTRAINT `fk_orders_customer` FOREIGN KEY (`customer_id`) REFERENCES `customers` (`id`))
DELETE IGNORE (a warning, the parent row is kept)
Warning (Code 1451): Cannot delete or update a parent row: a foreign key constraint fails (`shop`.`orders`, CONSTRAINT `fk_orders_customer` FOREIGN KEY (`customer_id`) REFERENCES `customers` (`id`))
Error 1217, the older short form without constraint details (in the server catalogue; not seen in these tests)
ERROR 1217 (23000): Cannot delete or update a parent row: a foreign key constraint fails
Error number
1451
SQLSTATE
23000
Symbol
ER_ROW_IS_REFERENCED_2
Product
MySQL Server
Versions
MySQL 5.7, 8.0 and 8.4 (InnoDB tables with FOREIGN KEY constraints)
Last reviewed
24 October 2026

What it means

Error 1451 means you tried to delete a parent row, or change its key, while rows in a child table still reference it through a foreign key, so MySQL rejected the statement.

A foreign key protects child rows from losing their parent. With the default rule (no ON DELETE or ON UPDATE clause, which InnoDB treats as RESTRICT), deleting a customer who still has orders, or changing that customer's id, is rejected immediately with 1451. Note which table the message names: it is the child table that blocks you (`shop`.`orders`), with the constraint, the child column and the parent table you were changing.

The block can come from further down a chain. If orders cascade from customers but invoices still reference orders, deleting a customer names invoices, not orders. REPLACE also raises 1451, because it deletes the old parent row before inserting the new one. Emptying or dropping a referenced table gives different errors (1701 for TRUNCATE, 3730 for DROP TABLE). The opposite case, a child pointing at a missing parent, is error 1452.

Common causes

  • Deleting a parent row (a customer, product or category) that child rows still reference.
  • Updating a parent primary key value that child rows use, for example renumbering ids or changing a natural key such as a product code.
  • REPLACE INTO on a parent table: REPLACE deletes the existing row and inserts a new one, so the delete step is blocked.
  • A cascading delete reaches a table further down whose own foreign key has no ON DELETE CASCADE, so the whole statement is rolled back.
  • A cleanup or test-reset script deletes tables in the wrong order (parents before children).

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 tables reference the parent table, and with which rules?

SELECT rc.constraint_name, rc.table_name AS child_table, rc.referenced_table_name AS parent_table,
       rc.delete_rule, rc.update_rule
FROM information_schema.referential_constraints AS rc
WHERE rc.constraint_schema = DATABASE()
  AND rc.referenced_table_name = 'customers';
What to look for

Every foreign key pointing at customers. NO ACTION or RESTRICT blocks the delete; CASCADE deletes the children too; SET NULL clears the child column. Repeat the query for each child table to see the rest of the chain.

Find the child rows that block the change

Use the child table and column from the message and the parent key you were deleting or updating.

SELECT id, customer_id
FROM orders
WHERE customer_id = 1;
What to look for

The rows that still reference the parent. Each one must be moved, removed or allowed to cascade before the parent can go.

Count referencing rows per parent before a bulk delete

SELECT c.id, c.name, COUNT(o.id) AS order_count
FROM customers AS c
LEFT JOIN orders AS o ON o.customer_id = c.id
WHERE c.id IN (1, 2, 3)  -- the parents you plan to delete
GROUP BY c.id, c.name;
What to look for

Parents with order_count 0 can be deleted safely; the others will raise 1451.

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.

Deal with the child rows first, in one transaction

Changes data

If the children really should go, delete them (or move them to another parent) before the parent, inside one transaction so a failure leaves nothing half done. Work from the bottom of the chain up.

Caution: Deleting child rows removes real history such as orders and invoices. Confirm with the data owner, take a backup or copy the rows to an archive table first, and check the row count before COMMIT.

START TRANSACTION;
DELETE FROM orders WHERE customer_id = 1;
DELETE FROM customers WHERE id = 1;
COMMIT;

Deactivate the parent instead of deleting it

Changes data

For customers, products and similar records with history, a soft delete is usually what the business wants: keep the row and mark it inactive (this needs an is_active or deleted_at column). The orders keep a valid customer and reports still work.

UPDATE customers SET is_active = 0 WHERE id = 1;

Change the foreign key rule deliberately (CASCADE or SET NULL)

Changes schema

If children should always follow the parent, recreate the constraint with ON DELETE CASCADE; if they should survive without a parent, use ON DELETE SET NULL on a nullable column. Drop and add the constraint in one ALTER TABLE.

Caution: ON DELETE CASCADE makes every future delete of a parent silently remove its children, and further cascades below them. Only use it where that is the intended rule. ALTER TABLE on a large table can take time and lock writes, so plan a maintenance window.

ALTER TABLE orders
  DROP FOREIGN KEY fk_orders_customer,
  ADD CONSTRAINT fk_orders_customer FOREIGN KEY (customer_id)
      REFERENCES customers (id) ON DELETE CASCADE;

Do not change parent keys; use an upsert instead of REPLACE

Changes data

Keep primary keys stable and change other columns instead. Where REPLACE INTO hits 1451, INSERT ... ON DUPLICATE KEY UPDATE updates the row in place, so no delete happens.

INSERT INTO customers (id, name)
VALUES (1, 'Sara B')
AS new
ON DUPLICATE KEY UPDATE name = new.name;

Examples

Deleting a customer who still has orders

CREATE TABLE customers (
    id   INT PRIMARY KEY,
    name VARCHAR(100)
);
CREATE TABLE orders (
    id          INT PRIMARY KEY,
    customer_id INT NOT NULL,
    CONSTRAINT fk_orders_customer FOREIGN KEY (customer_id) REFERENCES customers (id)
);
INSERT INTO customers VALUES (1, 'Sara');
INSERT INTO orders VALUES (100, 1);

DELETE FROM customers WHERE id = 1;
Result
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`shop`.`orders`, CONSTRAINT `fk_orders_customer` FOREIGN KEY (`customer_id`) REFERENCES `customers` (`id`))

Reproduced on MySQL 8.0.46, 24 October 2026.

Changing a parent key that child rows use

CREATE TABLE customers (id INT PRIMARY KEY, name VARCHAR(100));
CREATE TABLE orders (
    id          INT PRIMARY KEY,
    customer_id INT NOT NULL,
    CONSTRAINT fk_orders_customer FOREIGN KEY (customer_id) REFERENCES customers (id)
);
INSERT INTO customers VALUES (1, 'Sara');
INSERT INTO orders VALUES (100, 1);

UPDATE customers SET id = 2 WHERE id = 1;
Result
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`shop`.`orders`, CONSTRAINT `fk_orders_customer` FOREIGN KEY (`customer_id`) REFERENCES `customers` (`id`))

Reproduced on MySQL 8.0.46, 24 October 2026.

REPLACE INTO on a referenced parent row

CREATE TABLE customers (id INT PRIMARY KEY, name VARCHAR(100));
CREATE TABLE orders (
    id          INT PRIMARY KEY,
    customer_id INT NOT NULL,
    CONSTRAINT fk_orders_customer FOREIGN KEY (customer_id) REFERENCES customers (id)
);
INSERT INTO customers VALUES (1, 'Sara');
INSERT INTO orders VALUES (100, 1);

REPLACE INTO customers VALUES (1, 'Sara B');  -- REPLACE deletes the old row first
Result
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`shop`.`orders`, CONSTRAINT `fk_orders_customer` FOREIGN KEY (`customer_id`) REFERENCES `customers` (`id`))

Reproduced on MySQL 8.0.46, 24 October 2026.

A cascade blocked further down the chain

CREATE TABLE customers (id INT PRIMARY KEY, name VARCHAR(100));
CREATE TABLE orders (
    id          INT PRIMARY KEY,
    customer_id INT NOT NULL,
    CONSTRAINT fk_orders_customer FOREIGN KEY (customer_id) REFERENCES customers (id) ON DELETE CASCADE
);
CREATE TABLE invoices (
    id       INT PRIMARY KEY,
    order_id INT NOT NULL,
    CONSTRAINT fk_invoices_order FOREIGN KEY (order_id) REFERENCES orders (id)  -- no CASCADE here
);
INSERT INTO customers VALUES (1, 'Sara');
INSERT INTO orders VALUES (100, 1);
INSERT INTO invoices VALUES (5000, 100);

DELETE FROM customers WHERE id = 1;
Result
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`shop`.`invoices`, CONSTRAINT `fk_invoices_order` FOREIGN KEY (`order_id`) REFERENCES `orders` (`id`))

Reproduced on MySQL 8.0.46, 24 October 2026.

How to prevent it

Decide the delete rule for every relationship when you design it: RESTRICT (the default) for records with history, CASCADE only for rows that have no meaning without their parent (such as order lines), and SET NULL for optional links. Prefer soft deletes for customers, products and accounts.

Keep primary keys stable and use upserts instead of REPLACE on parent tables. In cleanup and test scripts, delete children before parents. Handle error 1451 in application code so the user sees "this customer still has orders" rather than a database error.

Common questions

How do I fix MySQL error 1451?

Look at the child table named in the message, find the rows that reference the parent, and decide what should happen to them: move them, delete them first, or keep the parent and mark it inactive. Change the foreign key to CASCADE only if children should always be deleted with their parent.

Why does the message name a different table from the one I deleted from?

The message names the child table whose foreign key blocked the change. With cascading deletes it can be a table several levels below, because the cascade reached it and that table's own constraint does not cascade.

Is it safe to use SET FOREIGN_KEY_CHECKS = 0 to delete the row?

No. The parent is deleted but the child rows remain, pointing at a row that no longer exists, and MySQL does not re-check them when checks are switched back on. Reports that join the tables lose those rows, and re-creating that foreign key later fails with error 1452 until the orphans are resolved.

Does ON DELETE CASCADE also fix error 1451 on UPDATE?

No. ON DELETE only covers deletes. Changing a parent key needs ON UPDATE CASCADE, but the better habit is to keep primary keys stable and change other columns instead.

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.