INSERT, UPDATE and DELETE

SQL · Essentials · 12 min

Reading data is half the job; applications constantly create, change and remove rows.

INSERT adds rows. Always list the target columns, so the statement does not depend on column order and omitted columns get their defaults:

INSERT INTO customers (name, email, city)
VALUES ('Eve', 'eve@example.com', 'Paris'),
       ('Finn', 'finn@example.com', NULL);

One statement with several VALUES rows is much faster than many single-row inserts. INSERT INTO t (...) SELECT ... copies the result of a query.

UPDATE changes columns of the rows that match WHERE. The right-hand side can use the old values:

UPDATE products SET price = price * 1.10 WHERE category = 'hardware';

DELETE removes matching rows:

DELETE FROM orders WHERE status = 'cancelled';

The rule that saves careers: an UPDATE or DELETE without WHERE touches every row. Run the equivalent SELECT first, and when working by hand, do it inside a transaction (BEGIN; ... check the row count ... COMMIT; or ROLLBACK;).

RETURNING (PostgreSQL, SQLite and MariaDB; SQL Server's equivalent is OUTPUT) hands back the affected rows, so you can fetch a generated id or the new values without a second query. MySQL has no RETURNING; use LAST_INSERT_ID() there.

To empty a whole table, TRUNCATE orders is much faster than DELETE FROM orders because it does not visit rows one by one. It needs a stronger lock and does not fire row-level triggers, and in PostgreSQL it is still transactional.

Every statement reports how many rows it affected (UPDATE 3 in psql). Check that number in application code; an update that matched zero rows is often a bug.

Example

INSERT INTO customers (name, email, city)
VALUES ('Eve', 'eve@example.com', 'Paris')
RETURNING id, name;
--  id | name
--   5 | Eve

UPDATE products
SET price = price * 1.10
WHERE category = 'hardware'
RETURNING name, price;
--  Keyboard |  53.90
--  Mouse    |  21.45
--  Monitor  | 207.90

BEGIN;
DELETE FROM orders WHERE status = 'cancelled';   -- DELETE 1
-- looks right? COMMIT; otherwise:
ROLLBACK;

Remember

  • Always list the columns in INSERT
  • UPDATE/DELETE without WHERE affects every row
  • RETURNING gives you generated ids and new values in the same round trip
  • TRUNCATE empties a table far faster than DELETE

Watch out for

  • Running an UPDATE whose WHERE clause was accidentally not selected in the SQL editor.

Check yourself

  1. What does UPDATE products SET price = 0; do?
  2. What is the main benefit of INSERT ... RETURNING id?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: www.postgresql.org/docs/current/dml.html