能,但必须确保query()执行的是非SELECT语句;SELECT类语句应使用$result->num_rows,而INSERT/UPDATE/DELETE等用$mysqli->affected_rows,其返回-1表示不适用或出错,0表示执行成功但无实际变更。

mysqli_query() 后不能直接用 mysqli_affected_rows()?
能,但必须确保 query() 执行的是非 SELECT 语句。对 SELECT、SHOW、DESCRIBE 等返回结果集的语句,$mysqli->affected_rows 恒为 -1;此时该用 $result->num_rows。
常见错误是写完 $mysqli->query("SELECT ...") 就立刻查 affected_rows,结果得到 -1 还以为出错了。
-
INSERT/UPDATE/DELETE/REPLACE:查$mysqli->affected_rows -
SELECT/EXPLAIN:查$result->num_rows(需先判断$result是否为mysqli_result对象) - 执行失败时(如语法错、字段不存在),
$mysqli->affected_rows也是 -1,但此时更应优先检查$mysqli->errno和$mysqli->error
为什么 $mysqli->affected_rows 有时返回 0?
0 表示语句执行成功,但没实际变更任何行——这不等于失败,而是真实业务状态。比如:
-
UPDATE users SET status=1 WHERE id=999,但 id=999 不存在 → 返回 0 -
UPDATE users SET name='alice' WHERE id=123,但当前 name 已是 'alice' → MySQL 优化后不触发更新,也返回 0 DELETE FROM logs WHERE created_at ,匹配到 100 行但全被 WHERE 过滤掉 → 仍为 0
所以不能仅靠是否为 0 判断逻辑错误,得结合业务意图。登录验证时查不到用户,affected_rows 是 0,但这是预期行为;而批量发通知后返回 0,就该告警。
mysqli_affected_rows() 和 ROW_COUNT() 函数的区别
PHP 层的 $mysqli->affected_rows 底层调用的就是 MySQL 的 ROW_COUNT() 函数,二者行为完全一致。但要注意:
- 它反映的是存储引擎层面“真实变更量”,不是 SQL 语法上“WHERE 匹配了多少行”
-
INSERT ... ON DUPLICATE KEY UPDATE:无冲突插入 → 返回 1;有冲突且更新字段值变化 → 返回 1;有冲突但更新字段值未变 → 返回 0 -
REPLACE INTO:删除 + 插入共 2 行变更 → 返回 2 -
INSERT IGNORE:插入成功 → 1;主键/唯一键冲突跳过 → 0
别把 affected_rows 当成“WHERE 条件命中数”来用,尤其在带条件的 UPDATE 场景下,容易误判。
事务中怎么安全获取影响行数?
在事务里执行多条语句时,$mysqli->affected_rows 始终只反映**上一条** query() 的结果,不会累积或清空。但它有个关键限制:
- 如果上一条是
SELECT,affected_rows是 -1,后续语句不受影响 - 但如果上一条是
INSERT/UPDATE/DELETE,再执行SELECT后,affected_rows会变成 -1,且**无法自动恢复前值** - 因此,需要立即保存:
$rows = $mysqli->affected_rows; $mysqli->query("SELECT ..."); // 此后 $mysqli->affected_rows 变为 -1
最容易被忽略的是:事务提交(commit)或回滚(rollback)本身不改变 affected_rows,但它们之后的任何新查询都会覆盖它。所以涉及多步变更的逻辑,每步都得当场捕获并存变量。











