MySQL存储过程中用ROW_COUNT()获取UPDATE影响行数,需在UPDATE后立即调用,中间不能有其他SQL;返回-1通常因无WHERE或引擎限制;与FOUND_ROWS()无关,后者用于SQL_CALC_FOUND_ROWS的SELECT。

MySQL存储过程中怎么拿到UPDATE影响了多少行
直接用 ROW_COUNT(),它返回上一条DML语句(INSERT、UPDATE、DELETE)实际变更的行数。注意:不是SQL语句写的“可能影响多少行”,而是真实被修改的行数(比如WHERE条件没匹配到,就返回0)。
常见错误是调用 ROW_COUNT() 前插了其他语句(哪怕只是 SELECT 1; 或变量赋值),它就会被覆盖——ROW_COUNT() 只认紧挨着的上一条数据变更操作。
- 必须在
UPDATE后立刻读取,中间不能有任何其他SQL执行 - 在存储过程中,建议立即存进用户变量或局部变量,例如:
SET @affected = ROW_COUNT(); - 如果UPDATE带了 LIMIT,
ROW_COUNT()返回的是实际更新的行数,不是LIMIT值
为什么有时候ROW_COUNT()返回-1
这是MySQL客户端或连接层的兼容性行为,不是错误。当上一条语句是非事务性引擎(如MyISAM)的UPDATE,或启用了 sql_safe_updates=1 且未加WHERE/KEY限制时,ROW_COUNT() 可能返回-1。
- InnoDB表+正常UPDATE + 显式WHERE条件,基本不会出现-1
- 若遇到-1,先检查是否漏写了WHERE,或执行了
UPDATE t SET x=1;这类无条件全表更新(此时MySQL会拒绝并报错,但某些旧版本或配置下可能返回-1) - 不建议靠判断-1来写逻辑分支;更稳妥的做法是:确保UPDATE有有效WHERE,并依赖返回≥0的值做后续处理
在IF或循环里用ROW_COUNT()要注意什么
最容易踩的坑是控制流干扰了“上一条语句”的指向。比如在 IF ... THEN ... END IF; 块里执行UPDATE,然后在块外读 ROW_COUNT(),看似没问题,但如果IF分支里还有别的UPDATE,或者ELSE里也有,那最终结果取决于最后执行的是哪条。
- 每个UPDATE后,如果需要该结果,就立刻保存,不要延迟到分支合并之后
- 避免在循环体中反复UPDATE同一张表却不捕获每次的
ROW_COUNT(),否则只能拿到最后一次的值 - 示例:正确写法是
UPDATE t SET status='done' WHERE id = v_id; SET v_cnt = ROW_COUNT();,而不是UPDATE完跳出去再统一查
ROW_COUNT()和FOUND_ROWS()有什么区别
ROW_COUNT() 看的是刚执行的DML改了几行;FOUND_ROWS() 是配合 SELECT SQL_CALC_FOUND_ROWS ... 用的,返回满足WHERE条件的总行数(无视LIMIT)。两者完全无关,别混用。
- 现在官方已废弃
SQL_CALC_FOUND_ROWS,性能差,推荐改用子查询或两次SELECT - 如果你看到别人代码里写了
SELECT FOUND_ROWS(),说明它前面一定有带SQL_CALC_FOUND_ROWS的SELECT,跟UPDATE和ROW_COUNT()没半点关系 - 存储过程中几乎不需要
FOUND_ROWS(),专注用好ROW_COUNT()就够了
真正麻烦的不是记不住函数名,而是忘记它只“保鲜”一瞬间——任何中间语句都会让它失效。上线前务必在真实并发场景下测几轮,尤其注意日志打印、异常处理分支里有没有偷偷执行了别的SQL。


















