MySQL UPDATE Statement
The UPDATE statement changes values in existing rows: a new salary, a corrected email, a new order status. It is the "U" in CRUD. Because a mistake can change thousands of rows at once, this tutorial also covers how to update safely.
1. Syntax
UPDATE table_name
SET column1 = value1, column2 = value2, ...
[WHERE condition]
[ORDER BY ...] [LIMIT n];
WHERE clause decides which rows change. Without it, every row is updated.Table: employees (6 rows)
| emp_id | name | dept | salary | rating | updated_at | |
|---|---|---|---|---|---|---|
| 1 | Asha | IT | 60000.00 | 4 | asha@old.example | NULL |
| 2 | Bilal | HR | 45000.00 | 3 | bilal@old.example | NULL |
| 3 | Chen | IT | 72000.00 | 5 | chen@old.example | NULL |
| 4 | Dia | Sales | 50000.00 | 2 | dia@old.example | NULL |
| 5 | Eshan | Sales | 53000.00 | 4 | eshan@old.example | NULL |
| 6 | Farah | HR | 47000.00 | 5 | farah@old.example | NULL |
2. Updating One Row
UPDATE employees SET rating = 4 WHERE emp_id = 4;
Query OK, 1 row affected
Rows matched: 1 Changed: 1 Warnings: 0
MySQL reports two numbers: rows matched by the WHERE clause and rows actually changed. Running the same update again matches 1 row but changes 0, because the value is already 4, so "0 rows affected":
UPDATE employees SET rating = 4 WHERE emp_id = 4;
Query OK, 0 rows affected
Rows matched: 1 Changed: 0 Warnings: 0
3. Updating Several Columns and Using Calculations
UPDATE employees
SET salary = salary * 1.10,
rating = LEAST(rating + 1, 5)
WHERE dept = 'IT';
SELECT name, dept, salary, rating FROM employees WHERE dept = 'IT';
Result: 2 rows
| name | dept | salary | rating |
|---|---|---|---|
| Asha | IT | 66000.00 | 5 |
| Chen | IT | 79200.00 | 5 |
SET a = a + 1, b = a gives b the incremented value. Many other databases use the old value instead.4. Updating Text with Functions
UPDATE employees
SET email = REPLACE(email, '@old.example', '@corp.example');
SELECT name, email FROM employees ORDER BY emp_id LIMIT 3;
Result: 3 rows
| name | |
|---|---|
| Asha | asha@corp.example |
| Bilal | bilal@corp.example |
| Chen | chen@corp.example |
5. Different Values per Row with CASE
UPDATE employees
SET salary = CASE
WHEN rating = 5 THEN salary * 1.15
WHEN rating = 4 THEN salary * 1.08
ELSE salary * 1.03
END
WHERE dept IN ('HR', 'Sales');
SELECT name, dept, rating, salary FROM employees WHERE dept IN ('HR', 'Sales') ORDER BY emp_id;
Result: 4 rows
| name | dept | rating | salary |
|---|---|---|---|
| Bilal | HR | 3 | 46350.00 |
| Dia | Sales | 4 | 54000.00 |
| Eshan | Sales | 4 | 57240.00 |
| Farah | HR | 5 | 54050.00 |
6. UPDATE with a JOIN
Use another table's values in the update. Give each employee a bonus percentage from departments:
ALTER TABLE employees ADD COLUMN bonus DECIMAL(10,2) DEFAULT 0;
UPDATE employees e
JOIN departments d ON d.dept = e.dept
SET e.bonus = ROUND(e.salary * d.bonus_pct / 100, 2);
SELECT name, dept, salary, bonus FROM employees ORDER BY emp_id;
Result: 6 rows
| name | dept | salary | bonus |
|---|---|---|---|
| Asha | IT | 66000.00 | 5280.00 |
| Bilal | HR | 46350.00 | 2317.50 |
| Chen | IT | 79200.00 | 6336.00 |
| Dia | Sales | 54000.00 | 5400.00 |
| Eshan | Sales | 57240.00 | 5724.00 |
| Farah | HR | 54050.00 | 2702.50 |
7. UPDATE with a Sub-query
UPDATE employees
SET rating = rating + 1
WHERE rating < 5
AND salary < (SELECT avg_sal FROM (SELECT AVG(salary) AS avg_sal FROM employees) AS t);
SELECT name, salary, rating FROM employees ORDER BY emp_id;
Result: 6 rows
| name | salary | rating |
|---|---|---|
| Asha | 66000.00 | 5 |
| Bilal | 46350.00 | 4 |
| Chen | 79200.00 | 5 |
| Dia | 54000.00 | 5 |
| Eshan | 57240.00 | 5 |
| Farah | 54050.00 | 5 |
MySQL doesn't let a sub-query read the same table you are updating directly; wrapping it in a derived table (AS t) works around this:
UPDATE employees SET rating = 1 WHERE salary = (SELECT MIN(salary) FROM employees);
ERROR 1093 (HY000): You can't specify target table 'employees' for update in FROM clause
8. ORDER BY and LIMIT
Update only the first N rows in a chosen order, for example the two lowest-paid employees:
UPDATE employees SET salary = salary + 2000 ORDER BY salary ASC LIMIT 2;
SELECT name, salary FROM employees ORDER BY salary LIMIT 3;
Result: 3 rows
| name | salary |
|---|---|
| Bilal | 48350.00 |
| Farah | 54050.00 |
| Dia | 56000.00 |
This also helps update huge tables in small batches (… WHERE processed = 0 LIMIT 5000, repeated) without long locks.
9. Updating Safely
The classic accident is forgetting the WHERE clause. Protect yourself:
- Run the WHERE clause as a
SELECTfirst and check the rows. - Wrap risky updates in a transaction and
ROLLBACKif the count is wrong. - Turn on safe-update mode: it rejects UPDATE/DELETE without a key in WHERE or a LIMIT. The
mysqlclient enables it with--safe-updates; MySQL Workbench has it on by default.
SET sql_safe_updates = 1;
UPDATE employees SET dept = 'IT'; -- no WHERE: rejected
Query OK, 0 rows affected
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column.
SET sql_safe_updates = 0;
START TRANSACTION;
UPDATE employees SET dept = 'IT'; -- oops
SELECT dept, COUNT(*) FROM employees GROUP BY dept;
ROLLBACK;
SELECT dept, COUNT(*) AS staff FROM employees GROUP BY dept ORDER BY dept;
Inside the transaction
| dept | COUNT(*) |
|---|---|
| IT | 6 |
After ROLLBACK
| dept | staff |
|---|---|
| HR | 2 |
| IT | 2 |
| Sales | 2 |
10. Updating from Java
String sql = "UPDATE employees SET salary = salary * ? WHERE dept = ?";
try (PreparedStatement ps = con.prepareStatement(sql)) {
ps.setBigDecimal(1, new BigDecimal("1.05"));
ps.setString(2, "HR");
int changed = ps.executeUpdate(); // number of rows affected
System.out.println(changed + " employees updated");
}
executeUpdate() returns the number of rows matched by the WHERE clause, even if some already had the new value. Add useAffectedRows=true to the JDBC URL to get the number of rows actually changed, as the mysql client reports.11. Practice Exercises
Exercise 1: Give everyone in Sales with rating 4 or more a 5% raise.
UPDATE employees SET salary = salary * 1.05 WHERE dept = 'Sales' AND rating >= 4;
SELECT name, salary FROM employees WHERE dept = 'Sales';
Result: 2 rows
| name | salary |
|---|---|
| Dia | 58800.00 |
| Eshan | 60102.00 |
Exercise 2: Set each employee's rating to 3 if it's below 3, using one statement with no CASE.
UPDATE employees SET rating = 3 WHERE rating < 3;
SELECT name, rating FROM employees ORDER BY emp_id;
Result: 6 rows
| name | rating |
|---|---|
| Asha | 5 |
| Bilal | 4 |
| Chen | 5 |
| Dia | 5 |
| Eshan | 5 |
| Farah | 5 |
12. Summary
UPDATE t SET col = value WHERE …;changes matching rows; without WHERE, all rows change.- Update several columns at once, use expressions, functions and CASE.
- Join other tables or use (derived) sub-queries for values from elsewhere.
- ORDER BY + LIMIT updates a limited number of rows.
- Check with SELECT first, use transactions, and consider safe-update mode.