Navicat 15“影响行数”显示为0或偏少,主因是依赖MySQL的mysql_affected_rows()值,受SQL模式、SQL_SAFE_UPDATES、连接复用及协议解析限制;应关闭安全模式、启用服务器端行计数、避免批处理并以SELECT ROW_COUNT()为准。
Navicat 15 执行 UPDATE/DELETE 后“影响行数”显示为 0 或明显偏少
这不是 navicat 假装没执行,而是它默认依赖 mysql 服务端返回的 mysql_affected_rows() 值,而该值受会话级 sql 模式和客户端协议行为影响。尤其在 navicat 15 中,若未显式开启“报告实际影响行数”,它可能直接取 row_count() 的会话快照(比如被前面语句污染),或因协议压缩丢弃了真实计数。
实操建议:
- 执行 SQL 前,先在当前连接中运行:
SET SESSION sql_mode = '';—— 排除STRICT_TRANS_TABLES或NO_AUTO_VALUE_ON_ZERO等模式干扰行数统计逻辑 - 确认 Navicat 的「查询」→「选项」→「执行」页中勾选了
显示影响的行数和启用服务器端行计数(部分版本叫Use server-side row count) - 避免在同个查询窗口里混写多条语句(如
UPDATE; SELECT ROW_COUNT();),Navicat 15 对分号分隔的批处理行数反馈不稳定;拆成单条执行更可靠 - 如果刚执行过
INSERT ... ON DUPLICATE KEY UPDATE,注意ROW_COUNT()返回的是“变更行数 + 插入行数”的混合值,不是纯更新数;此时应改用SELECT ROW_COUNT() AS affected;单独查
为什么 SET SQL_SAFE_UPDATES=1 会导致影响行数始终为 0
当会话中启用了 SQL_SAFE_UPDATES=1(Navicat 新建连接有时默认开启),MySQL 会拒绝执行没有 WHERE 条件或 WHERE 不含索引列的 UPDATE/DELETE,并返回警告而非错误——但 Navicat 15 将这类“被拦截但未报错”的操作统一记为 0 行影响,不抛异常也不提示。
检查与修复:
- 执行
SELECT @@sql_safe_updates;确认是否为 1 - 临时关闭:
SET SQL_SAFE_UPDATES = 0;(仅限开发环境) - 若必须保留安全模式,确保 WHERE 条件明确命中主键或唯一索引,例如
WHERE id = 123,否则 Navicat 显示的 0 是 MySQL 主动拒绝执行的结果,不是 Bug
Navicat 15 连接复用导致上一条语句的 ROW_COUNT() 被误读
Navicat 15 默认复用连接池中的连接,而 ROW_COUNT() 是会话级函数,值只对上一条修改语句有效。如果你在同一个标签页里快速执行了 A 语句(UPDATE)、切到别的标签页干了点别的、再回来执行 B 语句(DELETE),B 的“影响行数”可能显示的是 A 的结果——因为 Navicat 没强制刷新会话状态。
最稳的应对方式:
- 每次执行关键 DML 前,手动加一句
SELECT ROW_COUNT() AS _rc;并看它的返回值,别信右下角状态栏的小数字 - 在「工具」→「选项」→「常规」中关闭
重用连接(Use connection pooling),强制每次新开会话(代价是连接建立稍慢,但数据反馈绝对干净) - 避免在「查询」窗口里用 Ctrl+Enter 批量执行多条 DML——Navicat 15 对这种场景的行数映射是未定义行为
真正容易被忽略的是:Navicat 15 的“影响行数”本质上是客户端对 MySQL 协议字段 server_status 和 affected_rows 的解析结果,不是实时调用函数。一旦中间有 PREPARE/EXECUTE、存储过程调用或 SHOW 语句穿插,这个链路就断了。信 SELECT ROW_COUNT(),别信状态栏数字。











