MySQL的ROW_COUNT()返回真正修改的行数,非仅WHERE匹配行;SQL Server的@@ROWCOUNT和PostgreSQL的GET DIAGNOSTICS均统计匹配行,含未变更者;跨库迁移需注意语义差异。
MySQL 里用 ROW_COUNT() 最直接
执行完 update 后,立刻查 row_count() 就是 mysql 官方推荐方式——它返回的是「值真正变了」的行数,不是 where 匹配到但没改成功的那些。比如把 name = 'alice' 改成 name = 'alice',这行不计入。
- 必须在同个连接、紧接 UPDATE 之后调用,中间不能有其他语句(包括 SELECT),否则会被覆盖
- 在存储过程中也有效,但要注意:函数作用域是当前会话,不是当前事务
- PHP 中更常用
$conn->affected_rows,它和ROW_COUNT()行为一致;但注意 mysqli 默认开启MYSQLI_CLIENT_FOUND_ROWS时会返回匹配行数而非变更行数,建议显式关闭
SQL Server 和 PostgreSQL 怎么看?别混用系统变量
SQL Server 用 @@ROWCOUNT,PostgreSQL 用 GET DIAGNOSTICS 或客户端接口,三者逻辑不同:SQL Server 和 PG 默认统计所有 WHERE 匹配的行,哪怕新旧值一样也计数;MySQL 则只算真改动的。
- SQL Server 示例:
UPDATE Users SET status='active' WHERE id=123; SELECT @@ROWCOUNT;—— 即使该用户 status 原来就是 'active',也返回 1 - PostgreSQL 中无法在纯 SQL 里直接 SELECT 行数,得靠客户端:psycopg2 用
cursor.rowcount,pgAdmin 执行后看底部状态栏提示 - Oracle 是
SQL%ROWCOUNT,仅限 PL/SQL 块内,不能在普通 SQL 窗口里用
程序里拿不到行数?检查驱动和执行链路
很多开发者发现 executeUpdate() 返回 0 或 -1,不是数据库没改,而是 JDBC 驱动版本太老、或用了 execute() 而非正确方法。
- Java JDBC 必须用
Statement.executeUpdate()或PreparedStatement.executeUpdate(),它返回 int 类型的受影响行数;execute()不保证返回值有意义 - Python 的 PyMySQL 默认支持
cursor.rowcount,但若启用了autocommit=False且未提交,有些旧版本会返回 -1 - .NET 的
SqlCommand.ExecuteNonQuery()返回值可靠,但注意:如果 UPDATE 前有 SET NOCOUNT ON,它会强制返回 -1 —— 这是 SQL Server 主动屏蔽了计数,得关掉
想提前知道影响多少行?别等执行完再后悔
用 EXPLAIN 配合 UPDATE(MySQL 8.0.19+、PostgreSQL)能预估扫描行数,但它不等于最终影响行数,因为 WHERE 条件是否命中、触发器是否修改数据、并发更新是否冲突,都会导致偏差。
- MySQL 8.0.19+ 支持
EXPLAIN UPDATE ...,看到rows_examined可判断是否全表扫描 - 更稳妥的做法是先
SELECT COUNT(*)带同样 WHERE 条件,但要注意:这个数可能比实际 UPDATE 行数多(比如被其他事务锁住或触发器过滤) - 线上环境严禁直接跑 UPDATE 看效果,务必先在测试库验证,尤其当 WHERE 条件漏写或索引失效时,
ROW_COUNT()返回一个异常大的数字就是危险信号
最常被忽略的一点:不同数据库对“影响”的定义根本不同,MySQL 认为值不变就不算影响,SQL Server 认为匹配即影响。跨数据库迁移脚本时,光看数字没用,得看它背后到底干了什么。










