mysqli::$affected_rows

mysqli_affected_rows

(PHP 5, PHP 7, PHP 8)

mysqli::$affected_rows -- mysqli_affected_rows获取先前 MySQL 操作中受影响的行数

描述

面向对象风格

过程化风格

mysqli_affected_rows(mysqli $mysql): int|string

返回最后一个 INSERTUPDATEREPLACEDELETE 查询所影响的行数。对于 SELECT 语句,其作用类似于 mysqli_num_rows()

参数

mysql

仅过程化风格:由 mysqli_connect()mysqli_init() 返回的 mysqli 对象

返回值

大于零的整数表示受影响的行数或检索的行数。零表示 UPDATE 语句未更新任何记录,查询中的 WHERE 子句没有匹配任何行,或者尚未执行任何查询。-1 表示查询返回错误,或者 mysqli_affected_rows() 被调用用于非缓冲的 SELECT 查询。

注意:

如果受影响的行数大于最大 int 值(PHP_INT_MAX),则受影响的行数将作为字符串返回。

示例

示例 #1 $mysqli->affected_rows 示例

面向对象风格

<?php

mysqli_report
(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* 插入行 */
$mysqli->query("CREATE TABLE Language SELECT * from CountryLanguage");
printf("受影响的行数 (INSERT): %d\n", $mysqli->affected_rows);

$mysqli->query("ALTER TABLE Language ADD Status int default 0");

/* 更新行 */
$mysqli->query("UPDATE Language SET Status=1 WHERE Percentage > 50");
printf("受影响的行数 (UPDATE): %d\n", $mysqli->affected_rows);

/* 删除行 */
$mysqli->query("DELETE FROM Language WHERE Percentage < 50");
printf("受影响的行数 (DELETE): %d\n", $mysqli->affected_rows);

/* 选择所有行 */
$result = $mysqli->query("SELECT CountryCode FROM Language");
printf("受影响的行数 (SELECT): %d\n", $mysqli->affected_rows);

/* 删除 Language 表 */
$mysqli->query("DROP TABLE Language");

过程化风格

<?php

mysqli_report
(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* 插入行 */
mysqli_query($link, "CREATE TABLE Language SELECT * from CountryLanguage");
printf("受影响的行数 (INSERT): %d\n", mysqli_affected_rows($link));

mysqli_query($link, "ALTER TABLE Language ADD Status int default 0");

/* 更新行 */
mysqli_query($link, "UPDATE Language SET Status=1 WHERE Percentage > 50");
printf("受影响的行数 (UPDATE): %d\n", mysqli_affected_rows($link));

/* 删除行 */
mysqli_query($link, "DELETE FROM Language WHERE Percentage < 50");
printf("受影响的行数 (DELETE): %d\n", mysqli_affected_rows($link));

/* 选择所有行 */
$result = mysqli_query($link, "SELECT CountryCode FROM Language");
printf("受影响的行数 (SELECT): %d\n", mysqli_affected_rows($link));

/* 删除 Language 表 */
mysqli_query($link, "DROP TABLE Language");

上面的示例将输出

Affected rows (INSERT): 984
Affected rows (UPDATE): 168
Affected rows (DELETE): 815
Affected rows (SELECT): 169

参见

添加注释

用户贡献的注释 8 个注释

匿名
13 年前
对于 "INSERT INTO ON DUPLICATE KEY UPDATE" 查询,虽然人们可能期望 affected_rows 在成功查询时每个行只返回 0 或 1,但实际上它可能会返回 2。

来自 Mysql 手册:"对于 ON DUPLICATE KEY UPDATE,每个行的 affected-rows 值为 1 如果该行作为新行插入,为 2 如果更新了现有行。"

参见:https://dev.mysqlserver.cn/doc/refman/5.0/en/insert-on-duplicate.html

以下是每个行的汇总分解。
+0:行没有更新或插入(可能是因为该行已经存在,但在 UPDATE 期间没有实际更改任何字段值)。
+1:插入了一行。
+2:更新了一行。
Jacques Amar
7 年前
在使用预处理语句时,即使没有结果集(例如在 UPDATE 或 DELETE 中),您仍然需要在 affected_rows 返回实际数字之前存储结果。

<?php
$del_stmt
->execute();
$del_stmt->store_result();
$count = $del_stmt->affected_rows;
?>

否则,事情会让人很沮丧。
Michael
9 年前
如果您需要具体知道 UPDATE 操作的 WHERE 条件是否未能匹配行,或者根本没有行需要更新,您需要检查 mysqli::$info。

由于它返回一个需要解析的字符串,您可以使用以下方法将结果转换为关联数组。

面向对象风格

<?php
preg_match_all
('/(\S[^:]+): (\d+)/', $mysqli->info, $matches);
$info = array_combine ($matches[1], $matches[2]);
?>

过程化风格

<?php
preg_match_all
('/(\S[^:]+): (\d+)/', mysqli_info ($link), $matches);
$info = array_combine ($matches[1], $matches[2]);
?>

然后,您可以使用该数组来测试不同的条件。

<?php
if ($info ['Rows matched'] == 0) {
echo
"此操作没有匹配任何行。\n";
} elseif (
$info ['Changed'] == 0) {
echo
"此操作匹配行,但没有行需要更新。\n";
}

if (
$info ['Changed'] < $info ['Rows matched']) {
echo (
$info ['Rows matched'] - $info ['Changed'])." 行匹配但未更改。\n";
}
?>

此方法可用于 mysqli::$info 支持的任何查询(INSERT INTO、LOAD DATA、ALTER TABLE 和 UPDATE),对于其他任何查询,它返回一个空数组。

对于任何 UPDATE 操作,返回的数组将包含以下元素。

数组
(
[Rows matched] => 1
[Changed] => 0
[Warnings] => 0
)
mishell dot mercer at gmail dot com
19 天前
请注意,如果您已关闭自动提交,并计划在提交之前执行多个操作,则 $affected_rows 仅在每个语句中有效。这意味着,例如,如果您想运行多个 INSERT 语句并在提交后统计所有插入的行,则需要实现一个运行计数器。

// 开始计数
$count = 0;

// 关闭自动提交
$mysqli->autocommit(FALSE);
$mysqli->begin_transaction;

// 插入几个项目
$query = "
INSERT INTO users ('id','username','email')
VALUES (1, 'userguy', '[email protected]'), (2, 'some_user', '[email protected]')
";
$mysqli->query($query);
echo $mysqli->affected_rows; // 2 - 正确
$count += $mysqli->affected_rows; // 添加到计数器

// 再插入一个
$query = "
INSERT INTO users ('id','username','email')
VALUES (3, 'anotherone', '[email protected]')
";
$mysqli->query($query);
$count += $mysqli->affected_rows;

// 再插入一个
$query = "
INSERT INTO users ('id','username','email')
VALUES (4, 'thefourth', '[email protected]')
";
$mysqli->query($query);
$count += $mysqli->affected_rows;

// 将这些语句提交到数据库
$mysqli->commit();

echo $mysqli->affected_rows; // 1 - 仅计算最后执行的语句
echo "实际计数:" . $count; // 4
fastest963 at gmail dot com
10 年前
empty($db->affected_rows) 即使 affected_rows 大于 0 也会返回 TRUE。如果您正在寻找失败,请手动检查 < 1。
anonymous
8 年前
这可能看起来很明显,但如果您执行 UPDATE,并且 SET 子句中的每个值都与表中已有的值完全相同,则 affected_rows 会返回 0。例如

<?php
$mysqli
= new mysqli($host, $usr, $pwd, $db, $port);
$appointment_date = "2015-12-07";
$sql = "update appointments set appointment_date = ? where appointment_id = 78";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param("s",$appointment_date);
$stmt->execute();
echo
$mysqli ->affected_rows . "<br>";
?>

当我第一次运行它后,在更改了 $appointment_date 变量的值后,它返回 1。当我第二次运行它(没有进行任何更改)时,它返回 0。我也验证了在不使用预处理语句的情况下相同的行为。
oilpc at oilpc dot com
14 年前
对于修改单个表中一行数据的 "INSERT" 或 "UPDATE" 语句,我检查了受影响的行数是否等于 1,以确定操作是否成功。它适用于错误和 WHERE 条件的假值(这可能根据特定应用程序用户的访问权限而生成)。
<?php
if ($mysqli->affected_rows==1){
echo
"success";
}
else {
echo
"fail";
}
?>

检查 mysqli->affected_rows 是否等于 -1 并不是确定 "INSERT IGNORE" 语句成功与否的好方法。例如:忽略插入用户提供数据的行时出现的重复键错误,只有当它们匹配指定的唯一约束时才会发生,即使插入了行,mysqli->affected_rows 也可能返回 -1 的值。(在 MySQL 5.0.85 linux 和 php 5.2.9-2 windows 上进行了测试)。但是,如果语句成功执行,mysqli->sqlstate 不会返回任何错误。
<?php
if ($mysqli->affected_rows!=-1){
echo
"success";// 对于 "INSERT IGNORE" 语句,如果在执行查询期间忽略了任何重复键错误,则不会发生。
}
else {
echo
"fail";// 导致任何重复键错误(但被忽略)的 "INSERT IGNORE" 语句会导致 mysqli->affected_rows 等于 -1
}

// 以下示例也适用于 "INSERT IGNORE" 语句
if ($mysqli->sqlstate=="00000"){
echo
"success";
}
else {
echo
"fail";
}
?>
lucgommans.nl
1 年前
在幕后,这会调用 mysql_affected_rows (1)。MariaDB 函数 ROW_COUNT() 提到了 (2) 它等效于该 C API 函数。这两行,SQL 后面跟着 PHP,应该等效。

SELECT ROW_COUNT();
$db->affected_rows;

我发现这对于在 SQL 提示符中双重检查事物很有用,以确保 affected_rows 反映了我的预期(更改的行,而不是更新语句中匹配的行),它确实做到了。

1. https://github.com/php/php-src/blob/1521cafee29e23ca147ec777f3770a7ac46c6880/ext/mysqli/mysqli_api.c#L36-L49
2. https://mariadb.com/kb/en/row_count/
To Top