INSERT, UPDATE & DELETE
Add, change and remove rows safely, including multi-row inserts, upserts and safe-update habits.
Reading data is only half the story. Applications constantly add, change and remove rows. SQL does this with three statements: INSERT, UPDATE and DELETE. They're simple to write and just as easy to get badly wrong, so this lesson also teaches the habits that keep your data safe.
Sample table#
INSERT: adding rows#
Always list the columns. The statement then keeps working if someone later adds a column or reorders them:
Insert many rows in one statement. This is much faster than one statement per row:
Columns you leave out get their default: stock becomes 0, and a nullable column with no default becomes NULL. You can also write DEFAULT explicitly as a value.
Getting the generated id. LAST_INSERT_ID() returns the AUTO_INCREMENT value from your connection's latest insert. For a multi-row insert, it returns the id of the first row:
Every driver has an equivalent (cursor.lastrowid in Python, getGeneratedKeys() in Java). Never use SELECT MAX(id) for this: another user might have inserted a row in the meantime.
Copying rows from a query with INSERT ... SELECT:
Handling duplicates: IGNORE, upserts and REPLACE#
sku is UNIQUE, so inserting an existing SKU normally fails:
You have three alternatives:
The upsert found the existing KB-01 and added 3 to its stock (12 → 15). Before 8.0.19 you'd write stock = stock + VALUES(stock). That still works but is deprecated.
The third option, REPLACE INTO, deletes the old row and inserts a new one. That gives it a new AUTO_INCREMENT id and fires delete triggers, so it's rarely what you want. Prefer the upsert.
INSERT IGNOREalso silences other errors, such as values that are too long, by converting them to warnings and adjusting the data. Use it only when you really mean "skip duplicates", and checkSHOW WARNINGS;afterwards.
UPDATE: changing rows#
SETcan change several columns, and expressions can use the current values (stock - 1).WHEREdecides which rows change. Leave it out and every row changes.
Update many rows with one condition, such as a 10% price rise on all cables:
You can update using another table by joining it in:
DELETE: removing rows#
That removed the laptop stand. As with UPDATE, a DELETE without WHERE removes every row. To delete rows that match another table, use a join and name the table to delete from:
ROW_COUNT() tells you how many rows the previous statement changed, and the mysql client prints it too (Query OK, 1 row affected).
Safe-change habits#
-
SELECT first. Write the
WHEREclause as aSELECT, check the rows, then changeSELECT *toUPDATE ... SETorDELETE. -
Use safe-updates mode while learning. It blocks
UPDATE/DELETEstatements that don't use a key inWHERE(and have noLIMIT):SQLOutputStart the client with
mysql --safe-updatesto have it on for the whole session. -
Wrap risky changes in a transaction so you can undo them:
SQLOutputYou'll learn transactions properly later. For now, remember that
ROLLBACKundoes everything sinceSTART TRANSACTION. -
Limit the blast radius.
UPDATE ... ORDER BY id LIMIT 1000changes big tables in small batches, so locks are held briefly.
Common mistakes#
- Quoting numbers and not quoting strings.
WHERE sku = KB-01makes MySQL try to subtract a column called01from a column calledKB. Strings need quotes:'KB-01'. - Column list and value list out of order. Values are matched to columns by position.
- Using
=with NULL.WHERE category = NULLnever matches anything. UseIS NULL. - Relying on
REPLACE. It deletes and reinserts, so ids change and foreign keys may cascade.
What's next#
Now that you can put data in, let's get good at getting it out. Next: SELECT in depth.
Check your understanding
Quick quiz
1.What happens if you run
UPDATE products SET price = 0;with no WHERE clause (and safe-updates mode off)?2.Which statement inserts a product or, if its unique
skualready exists, updates its stock instead?3.After inserting a row into a table with an AUTO_INCREMENT key, how do you get the new id in the same connection?
Finished reading?
Mark this lesson complete to track your progress.