MySQL存储过程中获取DML影响行数必须用ROW_COUNT()而非FOUND_ROWS(),因其仅对SELECT配合SQL_CALC_FOUND_ROWS有效;ROW_COUNT()须紧接目标语句调用,中间插入任何SQL都会导致结果错乱;INSERT ... ON DUPLICATE KEY UPDATE的返回值需结合业务逻辑判断;应用层需通过SELECT ROW_COUNT()或OUT参数获取,且ROW_COUNT()反映执行意图而非最终持久化结果。

MySQL存储过程里必须用ROW_COUNT(),不是FOUND_ROWS()
存储过程内想拿上一条UPDATE、INSERT或DELETE影响了多少行,唯一可靠方式是调用ROW_COUNT()函数。它返回的是「值真正变化」的行数,比如UPDATE t SET x=1 WHERE id=5执行时x原本就是1,这行就不计入。而FOUND_ROWS()只对SELECT配合SQL_CALC_FOUND_ROWS有效,用在DML后会返回0或不可预期值。
ROW_COUNT()必须紧接在目标语句后调用,中间不能有任何其他SQL
哪怕加一行SELECT 1;或IF @x > 0 THEN ... END IF;,都会让ROW_COUNT()返回上一条语句的结果,不是你想要的那条。常见错误包括:
- 在
UPDATE后写SELECT ROW_COUNT();——看似合理,但其实多了一条SELECT语句,已覆盖前值 - 把
ROW_COUNT()放在IF判断块里,而IF本身算一条语句 - 用
SET @cnt = ROW_COUNT();之前,先做了SELECT @debug := 'start';
正确做法:更新完立刻赋值,例如UPDATE users SET status='active' WHERE id = @uid; SET @affected = ROW_COUNT();
注意INSERT ... ON DUPLICATE KEY UPDATE的返回值特殊
这种语句的ROW_COUNT()返回值有三种可能:
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
- 1:新插入一行
- 2:已有记录被更新(先删后插模拟)
- 0:存在重复键,但
UPDATE子句中所有字段值都和原值相同(即没真改)
如果业务需要区分“插入”和“更新”,不能只看是否大于0,得结合逻辑判断;若需统一计为“有变更”,可加CLIENT_FOUND_ROWS连接参数,让ROW_COUNT()对未变字段也返回1,但要注意这会影响整个连接的行为。
从应用层拿到这个数,别依赖ExecuteNonQuery()返回值
存储过程内部用了ROW_COUNT(),不代表C#或Java能自动拿到。原因:
-
SqlCommand.ExecuteNonQuery()默认返回存储过程最后一个语句的影响行数,但前提是没开SET NOCOUNT ON - 一旦过程里写了
SET NOCOUNT ON,它就固定返回-1,完全不可用 - 稳妥方案是在过程末尾加
SELECT ROW_COUNT();,再用ExecuteScalar()取值;或者定义OUT参数,显式赋值后传出
最易忽略的一点:ROW_COUNT()是会话级的,不是事务级。如果你在存储过程中开了事务又回滚了,它仍保留回滚前的值——它不反映最终持久化结果,只反映语句执行时的变更意图。










