iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

DELETE

DELETE removes rows that match a WHERE clause. RETURNING gives you the deleted rows back — perfect for audit logs and undo. Forgetting WHERE empties the table.

Targeted, RETURNING, USING, soft-delete

EXAMPLE
-- Basic
DELETE FROM users WHERE id = 42;

-- RETURNING — get the row(s) back
DELETE FROM users
WHERE id = 42
RETURNING id, email, deleted_at;

-- DELETE … USING — delete based on another table
DELETE FROM posts p
USING  users u
WHERE  p.user_id = u.id
  AND  u.banned = true;

-- LIMIT-like deletes — via CTE (Postgres has no LIMIT on DELETE)
WITH old AS (
    SELECT id FROM logs
    WHERE created_at < now() - INTERVAL '30 days'
    ORDER BY id
    LIMIT 10000
)
DELETE FROM logs WHERE id IN (SELECT id FROM old);

-- TRUNCATE — fast, locks the table, no row triggers
TRUNCATE TABLE sessions RESTART IDENTITY CASCADE;

-- ON DELETE CASCADE — let the schema clean child rows for you
CREATE TABLE posts (
    id BIGSERIAL PRIMARY KEY,
    user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    ...
);

-- Soft delete — keep the row, mark it deleted
UPDATE users SET deleted_at = now() WHERE id = 42;
-- And exclude by default at read time
SELECT * FROM users WHERE deleted_at IS NULL;

Why it matters

In a long-running transaction, DELETE generates an enormous WAL stream that can blow up replication. For big purges, batch into 5-10k row chunks with a CTE + LIMIT.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
DELETE FROM users
WHERE created_at < now() - interval '1 year'
RETURNING id;
Try it Yourself »

Discussion

Loading…