DELETE¶
Basic syntax¶
Basic DELETE¶
-- Delete one row by primary key
DELETE FROM users WHERE id = 1;
-- Delete by condition
DELETE FROM sessions WHERE expires < '2024-01-01 00:00:00';
-- Delete with multiple conditions
DELETE FROM orders WHERE user_id = 5 AND status = 'cancelled';
-- Delete with bind parameters
DELETE FROM tokens WHERE user_id = ? AND token = ?;
DELETE all rows¶
Omit WHERE to remove every row in the table:
Warning
There is no confirmation prompt. A DELETE without a WHERE clause removes all rows immediately and cannot be undone without a rollback. Use TRUNCATE TABLE for the same effect with identical semantics.
DELETE with RETURNING¶
RETURNING makes DELETE behave like a query — it returns the deleted rows.
-- Return the deleted row's id
DELETE FROM users WHERE id = 1 RETURNING id;
-- Return multiple columns
DELETE FROM sessions WHERE expires < NOW() RETURNING id, user_id;
In Go:
rows, err := db.Query(
`DELETE FROM sessions WHERE expires < ? RETURNING id, user_id`,
time.Now(),
)
defer rows.Close()
for rows.Next() {
var id, userID int64
rows.Scan(&id, &userID)
// handle deleted session
}
DELETE with subquery¶
-- Delete orders for banned users
DELETE FROM orders
WHERE user_id IN (SELECT id FROM users WHERE banned = true);
-- Delete the oldest sessions, keeping only the 10 most recent per user
DELETE FROM sessions
WHERE id NOT IN (
SELECT id FROM sessions
ORDER BY created_at DESC
LIMIT 10
);
TRUNCATE TABLE¶
TRUNCATE TABLE is shorthand for a full-table delete with no WHERE clause. It removes every row and maintains all indexes and foreign-key constraints exactly as a plain DELETE would.
It is semantically equivalent to:
Use TRUNCATE when intent matters for readability — it makes it explicit that you mean to empty the whole table, not that you forgot a WHERE clause.
-- Clear a cache table between test runs
TRUNCATE TABLE session_cache;
-- Reset a staging table before a bulk load
TRUNCATE TABLE import_staging;
After a TRUNCATE, unique constraint slots are freed so previously-inserted values can be reinserted:
INSERT INTO users (email) VALUES ('alice@example.com');
TRUNCATE TABLE users;
INSERT INTO users (email) VALUES ('alice@example.com'); -- succeeds
Notes¶
- Foreign-key constraints are checked on delete when
PRAGMA foreign_keys = on(the default). Deleting a parent row that has child rows referencing it returns an error. RETURNINGreturns the row values before deletion — useful for audit logging or cascading application logic.- Omitting
WHEREdeletes all rows. UseTRUNCATE TABLEfor identical semantics with a clearer intent.