How to delete from multiple tables in MySQL?
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
Deleting from multiple tables in MySQL is necessary when managing related data with foreign key relationships. When you delete a parent record, you typically need to delete associated child records as well. MySQL provides two main approaches: multi-table DELETE with JOIN and foreign key constraints with ON DELETE CASCADE.
Method 1: DELETE with JOIN
The multi-table DELETE statement removes rows from multiple tables in a single query:
Syntax
Example: Delete a User and Their Orders
Delete from One Table Based on Another
Delete from Three Tables
Method 2: ON DELETE CASCADE
Define the cascade behavior in the foreign key constraint so deletions propagate automatically:
Adding CASCADE to Existing Tables
Method 3: Multiple DELETE Statements in a Transaction
When you cannot use JOINs or CASCADE:
Method 4: Using Subqueries
Note: MySQL does not allow deleting from a table and selecting from it in the same query. Use a subquery workaround:
Comparison of Approaches
| Approach | Pros | Cons |
| DELETE JOIN | Single query, explicit control | Complex syntax, must list all tables |
| ON DELETE CASCADE | Automatic, clean schema | Hidden behavior, can cascade unexpectedly |
| Transaction | Clear ordering, safe | Multiple round trips, more verbose |
| Subqueries | Flexible filtering | Cannot self-reference in MySQL, slower |
Safe Deletion Pattern
Always preview before deleting:
Common Pitfalls
- Foreign key violations: Without CASCADE, deleting a parent row with existing child references fails:
Cannot delete or update a parent row: a foreign key constraint fails. Delete children first or use CASCADE. - Accidental cascade: CASCADE can propagate deletions further than expected. A single
DELETE FROM userscould wipe out orders, order_items, payments, and reviews if all have CASCADE constraints. Audit your schema carefully. - Missing WHERE clause:
DELETE users, orders FROM users JOIN orders ON ...without aWHEREclause deletes all matching rows across both tables. Always include aWHEREclause. - Performance: Multi-table deletes on large tables can lock rows for extended periods. Consider batching:
DELETE FROM orders WHERE user_id = 5 LIMIT 1000in a loop. - Backup: Always back up or use transactions with
ROLLBACKcapability before mass deletions.DELETEis not easily reversible without a backup.
Summary
- Use
DELETE t1, t2 FROM t1 JOIN t2 ON ...for explicit multi-table deletion - Use
ON DELETE CASCADEfor automatic propagation through foreign key relationships - Use transactions with multiple
DELETEstatements when order matters - Always preview with
SELECTbefore executingDELETEon production data - Be cautious with CASCADE — audit your foreign key chain to understand propagation depth
Related reading
- How to delete multiple rows in DynamoDB?
- How to delete N numbers of documents in mongodb
- How to deploy changes to a Cassandra CQL schema
- How to design a distributed application using a Message Broker and a Database?
- How to design a distributed write-heavy data store
- How to design key schema to have only one DynamoDB table per application?
- How to design key schema to have only one DynamoDB table per application?
- How to determine the right TiDB and TiDB-Ansible version?

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.