在使用PHP的mysqli扩展进行数据库操作时,multi_query函数可以让我们一次性执行多条SQL语句,这在批量处理数据时非常方便。但在执行多条语句后,如何正确获取受影响的行数(affected_rows)就成为了一个常见的疑问。
本文将结合mysqli::$affected_rows属性,讲解在multi_query场景下,如何正确使用及需要注意的问题。
mysqli::$affected_rows是mysqli对象的一个属性,表示最近一次执行的INSERT、UPDATE或DELETE语句所影响的行数。单条SQL语句执行时非常直观:
$mysqli = new mysqli('gitbox.net', 'user', 'password', 'database');
$mysqli->query("UPDATE users SET status=1 WHERE last_login > NOW() - INTERVAL 30 DAY");
echo "受影响的行数: " . $mysqli->affected_rows;
执行完这条更新语句后,affected_rows即为受影响的行数。
multi_query允许一次性执行多条SQL语句:
$sql = "UPDATE users SET status=1 WHERE id=1;";
$sql .= "UPDATE users SET status=2 WHERE id=2;";
$mysqli->multi_query($sql);
但此时,affected_rows的值会是什么呢?答案是:affected_rows只反映当前正在处理的结果集对应的受影响行数。由于multi_query需要循环处理每条语句的结果,必须一条一条去获取。
示例代码:
$mysqli = new mysqli('gitbox.net', 'user', 'password', 'database');
$sql = "UPDATE users SET status=1 WHERE id=1;";
$sql .= "UPDATE users SET status=2 WHERE id=2;";
$sql .= "DELETE FROM logs WHERE created_at < NOW() - INTERVAL 30 DAY;";
if ($mysqli->multi_query($sql)) {
do {
// 获取当前结果的受影响行数
echo "受影响行数: " . $mysqli->affected_rows . "\n";
// 准备处理下一个结果
} while ($mysqli->more_results() && $mysqli->next_result());
} else {
echo "执行失败: " . $mysqli->error;
}
这里我们用do...while循环逐条处理语句,每执行完一条就读取当前的affected_rows,才能准确获取每条语句的影响行数。
multi_query必须配合next_result()逐条遍历结果
不调用next_result(),只能拿到第一条语句的affected_rows,后面的语句会被忽略。
某些语句可能没有影响行数
例如SELECT语句,affected_rows返回-1。只对修改数据的语句有效。
出错时affected_rows可能为-1
如果SQL语句执行失败,affected_rows会返回-1。此时需通过$mysqli->error获取错误信息。
事务处理时要注意一致性
如果多个语句在事务中执行,单条语句的affected_rows不能保证事务整体的最终状态,需要根据事务提交与回滚来控制。
在multi_query执行多条SQL时,必须用循环配合next_result()才能遍历所有结果。
每条语句执行后,affected_rows才是当前语句的受影响行数。
注意检测错误状态和特殊语句对affected_rows的返回值。
对事务操作时,受影响行数只是辅助判断,最终状态以事务提交结果为准。
掌握了以上要点,你就能正确高效地使用mysqli::$affected_rows配合multi_query进行多条SQL的执行与结果处理。