found_rows() 在存储过程中需配合 sql_calc_found_rows 使用才能获取无 limit 的匹配行数,否则返回实际返回行数;它仅对最近 select 生效,动态 sql 中须将 sql_calc_found_rows 拼入语句,且 mysql 8.0.17+ 已废弃该功能。

FOUND_ROWS() 在存储过程中怎么用
直接在存储过程里调用 FOUND_ROWS() 是可行的,但它不返回“当前查询的行数”这种模糊概念——它只返回上一条 SELECT 语句的“匹配行数”,而且行为高度依赖是否加了 SQL_CALC_FOUND_ROWS。
常见错误是写完一个带 LIMIT 的 SELECT 就立刻 SELECT FOUND_ROWS(),结果得到的是实际返回的行数(比如 10),而不是去掉 LIMIT 后的总匹配数。这是因为没加 SQL_CALC_FOUND_ROWS。
- 必须在目标
SELECT语句中显式加上SQL_CALC_FOUND_ROWS,FOUND_ROWS()才能返回无LIMIT的理论匹配数 - 如果只是想查“这次
SELECT实际取到了几行”,不用任何修饰,执行完SELECT后直接SELECT FOUND_ROWS()就行(此时它等价于结果集行数) -
FOUND_ROWS()是会话级、语句级的,执行下一条SELECT就覆盖前值;要用就立刻存到变量里,比如SET @total = FOUND_ROWS();
为什么在存储过程里用 FOUND_ROWS() 容易出错
因为存储过程里常混用多种语句类型,而 FOUND_ROWS() 只对最近一次的 SELECT 生效,和 UPDATE/DELETE 无关——后者该用 ROW_COUNT()。
典型翻车场景:
- 先执行
SELECT SQL_CALC_FOUND_ROWS ... LIMIT 5;,再执行SELECT COUNT(*) FROM ...,然后才调FOUND_ROWS()→ 此时返回的是COUNT(*)查询的结果(1 行),不是你想要的分页总数 - 在动态 SQL 中用
PREPARE+EXECUTE,但没在EXECUTE前加SQL_CALC_FOUND_ROWS→ 动态语句不会自动继承该修饰,FOUND_ROWS()返回 0 或上一条静态SELECT的值 - 误把
FOUND_ROWS()当成类似 SQL Server 的@@ROWCOUNT,以为它对所有 DML 都有效 → 实际上UPDATE后必须用ROW_COUNT()
动态 SQL 场景下如何安全获取 FOUND_ROWS()
存储过程里拼接 SQL 并执行时,SQL_CALC_FOUND_ROWS 必须作为字符串的一部分拼进去,不能靠外部修饰。
示例(安全写法):
SET @sql = CONCAT('SELECT SQL_CALC_FOUND_ROWS * FROM users WHERE status = ? LIMIT ?', status_val, limit_val);
PREPARE stmt FROM @sql;
EXECUTE stmt USING @status_val, @limit_val;
DEALLOCATE PREPARE stmt;
SELECT FOUND_ROWS() INTO @total_count;
注意点:
-
SQL_CALC_FOUND_ROWS是 MySQL 特有语法,不能省略空格或写成小写(虽然 MySQL 通常不区分大小写,但这个关键词必须原样拼写) - 如果
WHERE条件里字段允许为NULL,FOUND_ROWS()返回值可能略小于COUNT(*)(原因见下条) - MySQL 8.0.17+ 已废弃
SQL_CALC_FOUND_ROWS,未来版本会移除;生产环境建议提前评估迁移路径
FOUND_ROWS() 和 COUNT(*) 的关键差异
别以为 SELECT FOUND_ROWS() 和 SELECT COUNT(*) 是等价替代——它们语义不同,性能特征也相反。
-
FOUND_ROWS()在加了SQL_CALC_FOUND_ROWS后,MySQL 会扫描全部匹配行(哪怕只取前 10 行),所以比单纯LIMIT查询慢;但它避免了二次全表扫描 -
COUNT(*)走索引统计(如 InnoDB 的元数据估算)可能极快,但精确计数仍需扫描;若用COUNT(非空列),遇到NULL值会被跳过,而FOUND_ROWS()在SQL_CALC_FOUND_ROWS模式下也会跳过NULL行(等价于COUNT(该列),不是COUNT(*)) - 真正容易被忽略的是:如果原始
SELECT用了JOIN或子查询,FOUND_ROWS()统计的是最终结果集行数,而COUNT(*)写法必须手动复现相同逻辑,否则结果不一致











