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 ...forSELECT *(same joins/filter) and eyeball the rows first, then wrap the delete in a transaction (BEGIN; ... COMMIT;) so you canROLLBACKif the count looks wrong. BigQuery requires aWHEREclause onDELETE(useWHERE TRUEonly 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.