Insert-or-update in one statement
Before 3.24 you had to do INSERT OR REPLACE (which deletes + reinserts, breaking foreign keys) or write your own select-then-insert-or-update. Modern SQLite has proper UPSERT:
INSERT INTO t(...) VALUES (...)
ON CONFLICT(unique_col) DO UPDATE SET other_col = excluded.other_col;The pseudo-table excluded refers to the row that would have been inserted. You can SET any subset of columns and use any expression.
RETURNING (3.35+) lets you get back data from the affected rows in the same round-trip:
INSERT INTO t(...) VALUES (...) RETURNING id, created_at;Combined, INSERT...ON CONFLICT...DO UPDATE...RETURNING handles 'create or update and tell me what happened' in one statement — the bread-and-butter of REST API write paths.
Self-reference: Pippa's
add_message uses INSERT...RETURNING to get the new message id back without a second SELECT. Combined with conn.row_factory = sqlite3.Row it returns the freshly-inserted row to the API in a single round-trip.