Updating and Deleting Data
Introduction
UPDATE changes existing rows; DELETE removes them. Forgetting WHERE can touch every row in a table—one of the most expensive mistakes in production. This chapter writes safe updates and deletes, compares DELETE vs TRUNCATE, and enables sql_safe_updates for protection.
Prerequisites
- SELECT Queries Basics
- Sample data in
blog_dev.usersandblog_dev.posts
UPDATE Syntax
Change one user display name:
UPDATE users
SET display_name = 'Ada Lovelace'
WHERE id = 1;Code explanation:
SETlists columns and new valuesWHERErestricts rows—always verify withSELECTfirst
Preview before update:
SELECT id, display_name FROM users WHERE id = 1;
UPDATE users
SET display_name = 'Ada Lovelace'
WHERE id = 1;
SELECT id, display_name FROM users WHERE id = 1;Update multiple columns:
UPDATE posts
SET
title = 'Hello MySQL (revised)',
published_at = NOW()
WHERE id = 1;UPDATE With Expression
Increment-style (numeric column example):
UPDATE users
SET is_active = IF(is_active = 1, 1, 1)
WHERE id = 2;Real pattern with counter column:
-- If view_count column existed:
-- UPDATE posts SET view_count = view_count + 1 WHERE id = 1;UPDATE With JOIN (MySQL)
Update posts titles for one author:
UPDATE posts p
INNER JOIN users u ON u.id = p.user_id
SET p.title = CONCAT('[Archived] ', p.title)
WHERE u.email = 'bob@example.com'
AND p.published_at IS NULL;Code explanation:
- Join identifies rows to update—still need selective
WHERE
DELETE Rows
Remove one post:
DELETE FROM posts WHERE id = 2;Delete all drafts (still scoped):
DELETE FROM posts WHERE published_at IS NULL;Verify count:
SELECT COUNT(*) FROM posts;DELETE vs TRUNCATE
| DELETE | TRUNCATE | |
|---|---|---|
| WHERE | Yes | No—all rows |
| Triggers | Fires | Does not fire |
| Rollback | Row-by-row in transaction | DDL-like reset |
| Speed | Slower large tables | Fast table empty |
| FK | Row rules apply | May fail if referenced |
Empty table for re-seed:
TRUNCATE TABLE posts;Recreate sample posts from Inserting Data if needed.
Warning
DELETE Without WHERE Deletes All Rows
DELETE FROM posts; -- removes every rowAlways run SELECT … WHERE with same condition first.
sql_safe_updates Mode
Session guard against keyless updates/deletes:
SET sql_safe_updates = 1;Now update/delete without WHERE using key or LIMIT fails:
-- ERROR 1175 without WHERE on indexed column or LIMIT
UPDATE users SET is_active = 0;Safe patterns:
UPDATE users SET is_active = 0 WHERE id = 3;
UPDATE users SET is_active = 0 WHERE id IN (1, 2) LIMIT 2;Check current setting:
SELECT @@sql_safe_updates;Disable for current session only if you know what you are doing:
SET sql_safe_updates = 0;Soft Delete Pattern (App Design)
Instead of physical delete, flag row:
ALTER TABLE users ADD COLUMN deleted_at DATETIME NULL;
UPDATE users SET deleted_at = NOW() WHERE id = 4;
SELECT * FROM users WHERE deleted_at IS NULL;Common in web apps—keeps history and simplifies undo.
Practice Checklist
- Update one row by primary key
- Delete rows with
WHERE - Try
sql_safe_updatesand confirm unsafe statement blocked - Never run unqualified
DELETEon production
FAQ
Rows matched vs changed?
UPDATE with same value: matched but changed count 0—MySQL reports both.
Delete parent with child posts?
Without ON DELETE CASCADE FK, delete fails or orphans—constraints chapter.
Undo DELETE?
Only via transaction ROLLBACK if not committed—or restore backup.
TRUNCATE reset AUTO_INCREMENT?
Usually resets counter to 1—verify if you rely on ids.
UPDATE LIMIT?
MySQL allows UPDATE … LIMIT n—useful with ordering for batch jobs.
ORM delete?
Hibernate/JPA generates DELETE—still verify WHERE in logs during dev.