Skip to content
Oracle Database

Oracle Error ORA-02292

integrity constraint violated - child record found

Applies to: Oracle Database 19c, 21c, 23ai and 26ai (same wording)
Last technically reviewed 24 October 2026 on Oracle Database Error Messages reference (26ai, 21c and 19c); not run locally
The full message
ORA-02292: integrity constraint (SHOP.ORDERS_CUSTOMER_FK) violated - child record found
Other forms of this message
A foreign key created without a name
ORA-02292: integrity constraint (SHOP.SYS_C008456) violated - child record found
SQL*Plus and SQLcl show the failing line first
ERROR at line 1:
ORA-02292: integrity constraint (SHOP.ORDERS_CUSTOMER_FK) violated - child record found
Error code
ORA-02292
Product
Oracle Database
Versions
Oracle Database 19c, 21c, 23ai and 26ai (same wording)
Last reviewed
24 October 2026

What it means

ORA-02292 means a DELETE (or an UPDATE of a key value) on a parent table would leave rows in a child table pointing at a key that no longer exists, so Oracle rejected the statement.

A foreign key protects child rows from losing their parent. Oracle's reference gives the cause as an attempt to delete a parent key value that has a foreign key dependency. Unless the foreign key was declared with an ON DELETE clause, Oracle does not allow you to delete referenced key values that have dependent rows, and the statement is rolled back. Changing a referenced key value with UPDATE is blocked in the same way.

The constraint named in the message is the foreign key on the child table, not the parent's primary key. Look it up to find which child table still holds rows. A parent table can be referenced by several child tables; the message names only one constraint, so check them all before retrying. Related errors: dropping a referenced table needs CASCADE CONSTRAINTS, and TRUNCATE of a parent table with an enabled foreign key raises a different error.

Common causes

  • A DELETE removes a parent row (a customer, a product) that still has child rows (orders, order lines).
  • A cleanup or archive job deletes parent tables before child tables.
  • An UPDATE changes a primary or unique key value that child rows reference.
  • A table has several child tables and only some were cleaned up before the parent delete.
  • A self-referencing table (for example employees and their manager) deletes a row that other rows point to.

Diagnose it

Read-only These queries only read the data dictionary (USER_, ALL_ and DBA_ views) and dynamic performance views (V$). They do not change data, privileges or settings, so they are safe to run first. DBA_ and V$ views need the matching privileges.

Which child table and columns does the constraint belong to?

SELECT c.table_name AS child_table, cc.column_name AS child_column,
       c.delete_rule, p.table_name AS parent_table
FROM all_constraints c
JOIN all_cons_columns cc
  ON cc.owner = c.owner AND cc.constraint_name = c.constraint_name
JOIN all_constraints p
  ON p.owner = c.r_owner AND p.constraint_name = c.r_constraint_name
WHERE c.owner = 'SHOP'
  AND c.constraint_name = 'ORDERS_CUSTOMER_FK'
ORDER BY cc.position;
What to look for

The child table and column that reference the parent. DELETE_RULE is NO ACTION for a plain foreign key, CASCADE or SET NULL when an ON DELETE clause was declared.

List every foreign key that references the parent table

A parent can have several children; find them all before deleting.

SELECT c.owner, c.table_name AS child_table, c.constraint_name, c.delete_rule, c.status
FROM all_constraints c
JOIN all_constraints p
  ON p.owner = c.r_owner AND p.constraint_name = c.r_constraint_name
WHERE c.constraint_type = 'R'
  AND p.owner = 'SHOP'
  AND p.table_name = 'CUSTOMERS';
What to look for

One row per child foreign key. ALL_CONSTRAINTS shows only tables you can access; a DBA can query DBA_CONSTRAINTS to see child tables in other schemas.

Count the child rows that block the delete

SELECT customer_id, COUNT(*) AS child_rows
FROM shop.orders
WHERE customer_id = 42  -- the parent key you tried to delete
GROUP BY customer_id;
What to look for

The number of child rows still pointing at the parent. Decide whether they should be deleted, moved to another parent or kept (in which case the parent must stay).

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.

Delete or reassign the child rows first, then the parent

Changes data

When the children really should go, delete them before the parent, in the same transaction, working from the lowest child table upwards. If they should be kept, point them at another parent instead.

Caution: This removes business data from several tables. Check the row counts with the read-only queries above first, keep the statements in one transaction, and make sure no other child tables reference these rows.

DELETE FROM shop.order_lines
WHERE order_id IN (SELECT id FROM shop.orders WHERE customer_id = 42);

DELETE FROM shop.orders WHERE customer_id = 42;

DELETE FROM shop.customers WHERE id = 42;

Keep the parent and mark it inactive instead

Changes data

Records such as customers or products often must stay because their orders, invoices or history refer to them. A status column keeps the history intact while hiding the row from everyday use.

UPDATE shop.customers
SET status = 'CLOSED'
WHERE id = 42;

Declare ON DELETE CASCADE or SET NULL as a design decision

Changes schema

If child rows have no meaning without the parent (order lines of an order), ON DELETE CASCADE makes Oracle remove them automatically; ON DELETE SET NULL clears the reference instead. This is a rule about the data model, not a quick fix: once declared, every future parent delete cascades.

Caution: A cascading delete can silently remove many rows in several tables. Agree the rule with the data owner, run it in a maintenance window (the table has no foreign key between the two statements) and never use it for records that must be kept for history or audit.

ALTER TABLE shop.order_lines DROP CONSTRAINT order_lines_order_fk;

ALTER TABLE shop.order_lines ADD CONSTRAINT order_lines_order_fk
  FOREIGN KEY (order_id) REFERENCES shop.orders (id)
  ON DELETE CASCADE;

Do not disable the constraint to force the delete

Read-only

Oracle's Action text mentions disabling the constraint. Doing so leaves orphan child rows behind, and the constraint cannot be enabled and validated again until they are removed. Deal with the child rows explicitly instead.

Examples

Deleting a customer who still has orders

Not reproduced here: no Oracle Database is installed for this site. The result shows the message format documented in Oracle's error reference, with this example's constraint name filled in (the tables are assumed to be in schema SHOP).

CREATE TABLE customers (id NUMBER PRIMARY KEY, email VARCHAR2(200));
CREATE TABLE orders (
    id          NUMBER PRIMARY KEY,
    customer_id NUMBER CONSTRAINT orders_customer_fk REFERENCES customers (id)
);

INSERT INTO customers VALUES (42, 'sara@example.com');
INSERT INTO orders VALUES (1001, 42);

DELETE FROM customers WHERE id = 42;
Expected result (documented format, not run)
ORA-02292: integrity constraint (SHOP.ORDERS_CUSTOMER_FK) violated - child record found

Changing a key value that child rows reference

Not reproduced here: no Oracle Database is installed for this site. The message format comes from Oracle's error reference and the names are illustrative. Surrogate keys that never change avoid this case entirely.

-- renumbering a customer whose orders still use the old id
UPDATE customers SET id = 4200 WHERE id = 42;
Expected result (documented format, not run)
ORA-02292: integrity constraint (SHOP.ORDERS_CUSTOMER_FK) violated - child record found

How to prevent it

Decide for each foreign key what should happen when a parent goes away (block, cascade or set null) and declare it when the table is created. Write cleanup and archive jobs to work from child tables up to parent tables.

Use surrogate keys that never change, so no UPDATE ever has to touch a referenced key. Prefer marking important parents as inactive over deleting them, and handle ORA-02292 in application code as "this item is still in use".

Common questions

How do I fix ORA-02292 child record found?

Look up the constraint to find the child table, count the child rows for the key, then delete or reassign them before the parent, or keep the parent and mark it inactive. Use ON DELETE CASCADE only when the data model really calls for it.

How do I find which table has the child records?

The constraint in the message is the foreign key on the child table. Query ALL_CONSTRAINTS with that name: TABLE_NAME is the child table, and ALL_CONS_COLUMNS gives its columns.

Should I just use ON DELETE CASCADE?

Only when child rows have no meaning without their parent, such as order lines of an order. For customers, products or anything with history, cascading deletes remove data you usually need to keep.

Learn more on CodeWithSQL

Official documentation

Last technically reviewed 24 October 2026; examples and diagnostics run on Oracle Database Error Messages reference (26ai, 21c and 19c); not run locally. Messages and explanations follow Oracle's Database Error Messages reference; no Oracle Database was available, so the examples were not run locally.

Still stuck on an Oracle error?

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