The Forgotten WHERE
What happens when an UPDATE has no WHERE? It changes every row of the table. This statement was supposed to move one customer to London:
UPDATE customers
SET city = 'London';Results says Rows changed: 14: all the customers of the shop now live in London, and their real cities are gone:
| name | city |
|---|---|
| Emma Clark | London |
| Liam Turner | London |
| Olivia Brown | London |
| … | … |
The database doesn't ask whether you're sure, and there's no Undo button. The same goes for DELETE, which you'll learn in the next exercise: without WHERE, it deletes every row of the table. It's one of the best-known mistakes in programming, and it happens to experienced programmers too, usually when they run a statement before they've finished writing it. Here, the next Run brings the data back. In a real database, the only way back is a backup, if there is one.
How to protect yourself:
- Write the
WHEREfirst and try it out with aSELECT. Before you change rows, look at them: a query with the sameWHEREshows exactly the rows that the change will touch. When it finds the right ones, turnSELECT … FROM customersintoUPDATE customers SET …and keep theWHEREas it is. - Check Rows changed. When you meant to change one customer, it should say 1. 14 means that something is wrong.
- Use a transaction, which can undo changes. You'll learn about transactions at the end of this lesson.
For example, Leo Walker has a new email. First the query:
SELECT id, name, email
FROM customers
WHERE id = 8;| id | name | |
|---|---|---|
| 8 | Leo Walker | leo.walker@mail.com |
It finds one row, the right one, so its WHERE can go into the UPDATE unchanged:
UPDATE customers
SET email = 'leo@walker.uk'
WHERE id = 8;A WHERE can also find other rows than you meant: more of them (AND goes before OR, and LIKE '%an%' finds more names than you'd expect), or none (= NULL never finds anything). A SELECT with the same WHERE shows you all that before any harm is done.
Instructions
Run the file. The first UPDATE has no WHERE: Results says Rows changed: 30, and the first query shows every order as refunded. Before you fix it, find the row it should change: at the very top of the file, write a query that shows the ID, the customer and the date of customer 3's orders from 2025-03-03. It should find just one:
| id | customer_id | ordered_at |
|---|---|---|
| 17 | 3 | 2025-03-03 |
Now add that WHERE to the first UPDATE. It changes 1 row, and the first query at the end shows only the three refunded orders:
| id | customer_id | ordered_at | status |
|---|---|---|---|
| 7 | 6 | 2024-06-01 | refunded |
| 17 | 3 | 2025-03-03 | refunded |
| 18 | 8 | 2025-03-28 | refunded |
The second UPDATE should lower the prices of the Action and RPG games that cost more than $35, which are three games, but it changes 6 rows. Try out its WHERE in a query, find out why it finds more games, and fix it. The last query should then show:
| title | genre | price |
|---|---|---|
| Robot Rebellion | Action | 35 |
| Shadow Ninja | Action | 25 |
| Star Pilots | Action | 35 |
| Zombie Town | Action | 30 |
| Dragon Forge | RPG | 35 |
| Knight's Oath | RPG | 55 |
Start programming for free
5/9