DELETE
DELETE removes rows from a table. Like UPDATE, its safety depends entirely on the WHERE clause — DELETE FROM table with no WHERE removes every single row. This page covers the basic form, deleting based on a join to another table, and habits worth building to avoid deleting the wrong rows.
Basic DELETE
Removing a single order
DELETE FROM orders WHERE order_id = 4021;
DELETE 1
DELETE ... USING
Similar to UPDATE ... FROM, PostgreSQL supports DELETE ... USING for deleting rows based on a join to another table. USING brings in the second table, and the join condition goes in WHERE alongside whatever other filtering the delete needs.
Deleting order items for cancelled orders
DELETE FROM order_items USING orders WHERE order_items.order_id = orders.order_id AND orders.status = 'cancelled';
DELETE 17
A quick look at RETURNING
DELETE can end with RETURNING to capture exactly which rows were removed, and their values, before they are gone — the only chance to see that data, since after the statement commits it no longer exists in the table.
Capturing a deleted row's data
DELETE FROM orders WHERE order_id = 4021 RETURNING *;
order_id | customer_id | order_date | status
----------+-------------+------------+---------
4021 | 17 | 2026-01-14 | pendingDELETE FROM table WHERE condition removes matching rows.
Omitting WHERE deletes every row in the table.
DELETE ... USING deletes rows based on a join to another table.
RETURNING captures the deleted rows' data before it is gone for good.
Rehearsing the WHERE clause as a SELECT first is the cheapest safety check available.