INSERT, UPDATE, DELETE
Change data safely, including transactions.
What you will learn
- Insert rows
- Update with WHERE
- Wrap changes in a transaction
Queries read data; three statements change it. Because they change data, the golden rule is: write the WHERE clause first, and run it as a SELECT to check what it matches before you UPDATE or DELETE.
INSERT INTO customers (name, country, age)
VALUES ('Margaret', 'US', 52);
INSERT INTO customers (name, country, age) VALUES
('Alan', 'UK', 41),
('Barbara', 'US', 47);Always name the columns so the statement survives table changes. Columns you omit receive their default (or NULL, or an auto-generated id).
UPDATE orders
SET status = 'shipped'
WHERE id = 10;
UPDATE customers
SET age = age + 1
WHERE country = 'UK';UPDATE orders SET status = 'x'; with no WHERE changes every row. The same goes for DELETE. Test with SELECT ... WHERE first.
DELETE FROM orders
WHERE status = 'refunded' AND total < 10;DELETE removes rows; DROP TABLE removes the whole table. Many systems prefer a soft delete: add a deleted_at column and filter on it, so data can be recovered.
Transactions
A transaction groups statements so they succeed or fail together. Moving money must subtract from one account and add to another; if the second step fails, the first must be undone. Databases guarantee this through the ACID properties (atomicity, consistency, isolation, durability).
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT; -- or ROLLBACK; to undo everything since BEGINUpsert
Sometimes you want "insert, or update if it already exists". PostgreSQL and SQLite support it:
INSERT INTO customers (id, name, country, age)
VALUES (1, 'Ada', 'UK', 37)
ON CONFLICT (id) DO UPDATE SET age = excluded.age;Try it yourself
Insert two products, raise the price of one by 10 percent, then delete any product priced under 1. Wrap it in a transaction.
Show solution
BEGIN;
INSERT INTO products (name, price) VALUES ('Pen', 1.50), ('Gum', 0.50);
UPDATE products SET price = price * 1.10 WHERE name = 'Pen';
DELETE FROM products WHERE price < 1;
COMMIT;