Insert, update & upsert

DELETE rows using a join to another table

3 min read

Deleting based on another table (e.g. remove orders whose customer is flagged) has real dialect differences.

PostgreSQL / DuckDB / Snowflake — USING:

DELETE FROM orders o
USING customers c
WHERE o.customer_id = c.id
  AND c.status = 'banned';

MySQL — name the table(s) to delete between DELETE and FROM:

DELETE o
FROM orders o
JOIN customers c ON c.id = o.customer_id
WHERE c.status = 'banned';

SQLite / BigQuery — no join in DELETE; use a subquery:

DELETE FROM orders
WHERE customer_id IN (
  SELECT id FROM customers WHERE status = 'banned'
);

Test before you delete. Swap DELETE ... for SELECT * (same joins/filter) and eyeball the rows first, then wrap the delete in a transaction (BEGIN; ... COMMIT;) so you can ROLLBACK if the count looks wrong. BigQuery requires a WHERE clause on DELETE (use WHERE TRUE only if you truly mean all rows).

The IN (subquery) form works everywhere, so reach for it when you want one statement that’s portable across all six dialects. To modify instead of delete, see UPDATE a table from a join.

Open the full version (with copy buttons) ↗

← All recipes