row_count()返回0说明update未匹配任何行,主因是where条件不匹配、隐式类型转换失败、事务未提交或权限限制,需用select验证条件、检查autocommit状态及执行row_count()确认。

Navicat 显示“Query OK”或“执行成功”,但实际数据没变、ROW_COUNT() 返回 0,这不是界面假象,而是 SQL 真的没改到任何行——常见于条件不匹配、隐式类型转换失败、事务未提交或权限限制。得主动查,不能信“成功”两个字。
为什么 WHERE 条件永远不命中
最典型场景:字段类型和值类型不一致,MySQL 不报错,但直接跳过匹配。
-
create_time是DATETIME,却写WHERE create_time = '2024-01-01'→ 实际等价于'2024-01-01 00:00:00',漏掉当天其余时间 - 字符串用双引号或中文全角引号:
WHERE status = “active”(错误)→ 被当作文本常量或列名,语法虽过,逻辑失效 - 判断 NULL 写成
= NULL→ 永远返回 false,应改用IS NULL - 字段含前导/尾随空格或不可见字符(如
\r),而条件值是干净字符串,=严格比对失败
怎么确认是不是真没改,而不是“改了但看不见”
别只看 Navicat 底部提示,必须手动验证执行上下文和结果。
- 执行完 UPDATE/DELETE 后,立刻补一句:
SELECT ROW_COUNT();—— 返回 0 就说明一行都没动 - 另开一个 Navicat 连接(新会话),执行相同 SELECT,确认数据是否真的变了;如果没变,大概率是没
COMMIT - 检查当前事务状态:
SELECT @@autocommit;,若为 0,且你没手动COMMIT,那变更只在当前会话可见 - 用
SHOW WARNINGS;查有没有被忽略的 warning,比如字段截断、隐式转换、NULL 插入 NOT NULL 字段
Navicat 计划任务里更隐蔽:@var 全被静默跳过
脚本里写了 SET @days = 30; DELETE FROM logs WHERE ts ?在计划任务中,<code>@days 根本不生效,整条 WHERE 等价于 ts ,条件恒假,<code>ROW_COUNT() 一定为 0。
- Navicat 计划任务调用的是命令行模式(类似
mysql -e),不支持交互式会话变量@var - 它不会报错,也不会警告,日志只写“SQL executed successfully”
- 唯一验证方式:在脚本末尾加
SELECT CONCAT('deleted ', ROW_COUNT(), ' rows');并检查输出 - 正确做法:把变量逻辑硬编码进函数,例如直接写
DATE_SUB(NOW(), INTERVAL 30 DAY)
最容易被忽略的一点:Navicat 从不在界面上告诉你“你的条件其实一条都没匹配上”。它把 0 rows affected 和 1000 rows affected 都显示为“执行成功”,你得自己加 ROW_COUNT() 或查数据,才能知道它到底干了什么。











