How to delete from multiple tables in MySQL?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
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

