PHP MySQL Update

UPDATE statements, affected rows, and the cost of a missing WHERE.

Beginner
Key PointsAn UPDATE without WHERE rewrites the whole table — SELECT first, then update.

Update one row

PHP
<?php
$stmt = $pdo->prepare("UPDATE users SET email = ?, age = ? WHERE id = ?");
$stmt->execute(["new@example.com", 31, 1]);

echo "更新行数: " . $stmt->rowCount() . "\n";
Output
更新行数: 1
rowCount() counts changed rows, not matched ones. Setting identical values returns 0 — not an error. To distinguish missing from unchanged, SELECT first.

Updating selected fields

When a form submits only some fields, build the SET list from an allowlist instead of overwriting every column.

PHP
<?php
$input = ["name" => "Tom Lee", "age" => 32];

$allowed = ["name", "email", "age", "status"];

$sets = [];
$params = [];
foreach ($input as $k => $v) {
    if (!in_array($k, $allowed, true)) {
        continue;
    }
    $sets[] = "$k = ?";
    $params[] = $v;
}

if (!$sets) {
    exit("没有可更新的字段");
}

$params[] = 1;
$sql = "UPDATE users SET " . implode(", ", $sets) . " WHERE id = ?";
echo $sql, "\n";

$stmt = $pdo->prepare($sql);
$stmt->execute($params);
echo "更新行数: " . $stmt->rowCount() . "\n";
Output
UPDATE users SET name = ?, age = ? WHERE id = ?
更新行数: 1

Column names come from the allowlist and values go through placeholders — the only correct way to build a dynamic UPDATE.

Forgetting WHERE

PHP
<?php
// 灾难:全表被改
$sql = "UPDATE users SET status = 0";
echo $sql, "\n";
echo "没有 WHERE,全部行都会变\n";

// 正确:先查再改
$sql = "UPDATE users SET status = 0 WHERE id = 1";
echo $sql, "\n";
Output
UPDATE users SET status = 0
没有 WHERE,全部行都会变
UPDATE users SET status = 0 WHERE id = 1
Enable sql_safe_updates in production — it rejects UPDATE/DELETE without a WHERE or without an index. Also available as mysql --safe-updates.

Concurrent updates

Two people editing the same row: the later write wins. Use optimistic locking or atomic operations.

PHP
<?php
// 乐观锁:带版本号更新
$id = 1;
$version = 3;

$stmt = $pdo->prepare("UPDATE users SET name = ?, version = version + 1 WHERE id = ? AND version = ?");
$stmt->execute(["Tom Lee", $id, $version]);

if ($stmt->rowCount() === 0) {
    echo "数据已被他人修改,请刷新后重试\n";
} else {
    echo "更新成功,版本变为 4\n";
}
Output
更新成功,版本变为 4

AND version = ? is the crux: a mismatch updates zero rows and the caller knows there was a conflict — the lightest optimistic lock.

Atomic increments

PHP
<?php
// 错:先读再写,并发下会丢更新
// $n = SELECT stock; UPDATE stock = $n - 1;

// 对:在数据库里做减法
$stmt = $pdo->prepare("UPDATE products SET stock = stock - ? WHERE id = ? AND stock >= ?");
$stmt->execute([1, 1, 1]);

if ($stmt->rowCount() === 0) {
    echo "库存不足\n";
} else {
    echo "扣减成功\n";
}
Output
扣减成功
WHERE stock >= ? both guards and serialises: insufficient stock updates zero rows, so stock never goes negative. Read-modify-write loses updates under concurrency.

Friends & Partners