update执行成功但数据没变,主因是where条件未匹配任何行,rowsaffected()返回0即为铁证;需用select复现where条件验证、注意大小写与null比较(is null)、排查go参数顺序、pdo逗号误写为and及触发器干扰。

UPDATE 执行成功但数据没变,不是语法错,而是它根本没改到任何行——RowsAffected() 返回 0 就是铁证。问题不在“能不能执行”,而在“有没有命中的那一行”。
WHERE 条件没匹配到任何行
这是最常见也最容易被忽略的静默失败点:语句合法、无报错、事务也提交了,但 WHERE 根本没捞出数据。
- 立刻用
SELECT * FROM table_name WHERE ...复现你的WHERE条件,确认至少返回一行 - 注意大小写:PostgreSQL 和部分 MySQL 配置(
lower_case_table_names = 0)下,status和Status是不同字段 -
WHERE status = NULL永远为 false,必须写成status IS NULL - 字符串字段可能带不可见空格,试试
WHERE TRIM(status) = 'active'或LENGTH(status)查长度
Go 中 Exec() 参数顺序颠倒
在 Go 的 database/sql 里,? 占位符严格按从左到右顺序绑定参数,错一位就全乱。
- SQL:
"UPDATE userinfo SET created = ? WHERE uid = ?"→ 第一个?是created值,第二个是uid条件 - 错误调用:
stmt.Exec(lastId, "2015-09-02")→ 把lastId塞给created,把日期字符串塞给uid字段 - 结果:
uid = '2015-09-02'匹配不到整型主键,RowsAffected()必为 0 - 修复:改成
stmt.Exec("2015-09-02", lastId),并加defer stmt.Close()
PDO 中 SET 子句误用 AND 替代逗号
PHP 开发者容易手滑,在 SET 后写 AND,这会让数据库把整个表达式当布尔运算来算,而不是多个赋值。
- 错误 SQL:
UPDATE t SET a = ? AND b = ? WHERE id = ?→ 实际执行的是a = (? AND b = ?),结果通常是0或1 - 正确写法:
UPDATE t SET a = ?, b = ? WHERE id = ? - 即使
execute()返回true,也不代表更新成功;务必检查$stmt->rowCount() - 开启异常模式:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION),避免错误被吞
触发器干扰或静默跳过
你以为 UPDATE 完了就完了?触发器可能在背后悄悄覆盖、拦截,甚至因条件不满足直接跳过。
- MySQL 8.0+ 默认跳过“无实际变更”的 UPDATE:比如
SET name = name或新旧值相同,整个触发器都不会运行 - 查触发器状态:
SELECT STATUS FROM information_schema.TRIGGERS WHERE TRIGGER_NAME = 'your_trigger',确保是ENABLED - AFTER UPDATE 触发器里再改本表,会直接报
ERROR 1442,但很多客户端不显示——得去 MySQL 错误日志搜这个错误码 - BEFORE 触发器中写
SET NEW.status := 'pending'(注意是:=,不是=)才真正赋值;=是判断
真正麻烦的从来不是报错,而是那些不报错、RowsAffected() 还返回 1、但数据就是不对的场景——尤其是触发器逻辑分支没走到,或者 Go 里参数顺序只差一位。











