How does an UPDATE change rows, and what do the expressions in the SET clause actually see?
An UPDATE finds every row that matches the WHERE clause and replaces the columns you list in the SET clause. The expressions on the right-hand side of the SET are evaluated against the current row, so an expression can refer to the column's old value and build on it.
CREATE TABLE tickets (
id INTEGER PRIMARY KEY,
title VARCHAR(160) NOT NULL,
status VARCHAR(20) NOT NULL,
priority INTEGER NOT NULL,
attempts INTEGER NOT NULL DEFAULT 0
);
INSERT INTO tickets (id, title, status, priority) VALUES
(1, 'Login page times out', 'open', 3),
(2, 'Invoice PDF is blank', 'open', 1),
(3, 'Export times out', 'open', 2);
UPDATE tickets
SET status = 'in_progress',
priority = priority - 1,
attempts = attempts + 1
WHERE id = 3;
SELECT id, title, status, priority, attempts FROM tickets ORDER BY id;Three rows come back. Ticket 3 now has status 'in_progress', priority 1 and attempts 1; the other two are untouched. The priority - 1 expression read the old value of 2 and stored 1, and attempts + 1 read 0 and stored 1.
Two rules about the SET expressions. All the right-hand sides are evaluated against the original row before any of them are written — the statements are not applied one at a time, so the order of the assignments within the SET clause does not matter. And a column you do not mention keeps its value, so an UPDATE that changes one column leaves the others alone.
The WHERE clause is the safety mechanism, and its absence is the single most common cause of a data incident. Without it, every row in the table is updated. That is not a syntax problem and it is not caught by the database; it is caught, if at all, by a human noticing afterwards. Even a WHERE clause on a non-unique column can match more rows than you expected, which is why the affected-row count is worth checking on every UPDATE that touches a production table.