【问题标题】:PHP / MySQLI: strange readings for affected_rowsPHP / MySQLI:affected_rows 的奇怪读数
【发布时间】:2014-04-16 10:45:12
【问题描述】:

我正在尝试辨别 replace into 查询是否导致直接写入,或者先删除然后写入。

The MySQL docs say 在前者的情况下,受影响的行数应该返回 1,或者在后者的情况下应该大于 1:

受影响的行数可以很容易地确定是否 REPLACE 只添加了一行或是否也替换了任何行:检查是否 计数为 1(添加)或更大(替换)。

然而,对我来说,通过 PHP 和 MySQLI 执行此操作,该值始终为 1,无论我的查询是直接写入还是先删除然后写入。

我有一个表“foo”,其中有一列:一个 varchar,它也是主键。所以一开始它是空的。我跑:

$sql = "REPLACE INTO foo VALUES('bar');"
$db->query($sql); //$db is an instantiated and working MySQLI instance
echo $db->affected_rows;

这给了我“1” - 很公平,这是一个直截了当的写法。但是,如果我再次运行相同的查询,它应该给我“2”,对吧?首先删除该行,然后重新插入它,因为主键是相同的。因此,有 2 行受影响。

顺便说一句,我已经尝试过使用基本查询和准备好的语句,即

$sql = "REPLACE INTO foo VALUES(?)";
$stmt = $db->prepare($sql);
$bar = "bar";
$stmt->bind_param('s', $bar);
$stmt->execute();
echo $stmt->affected_rows; //still 1

有什么想法!?

【问题讨论】:

    标签: php mysql sql mysqli


    【解决方案1】:

    根据我的实验和发现:

    就像手册中所说的那样,如果REPLACE 删除了一行并插入到位而不是INSERT,它将显示更大的数字。请注意它说的文档:

    请注意,除非表有 PRIMARY KEY 或 UNIQUE 索引,否则使用 REPLACE 语句没有意义。它等同于 INSERT, 因为没有索引可以用来判断是否有新行 复制另一个。

    因此,在replace 语句中,您必须传递主键或唯一键列的值。据我所知,您只传递了一个值。您需要为 REPLACE 提供一个键值,以便它识别在替换/插入之前应该检查哪个行值。

    另一个有趣的点是:

    如果满足以下条件,单行可能会替换多个旧行 该表包含多个唯一索引并且新行重复 不同唯一索引中不同旧行的值。

    这会产生大于 2 的数字,并且当您向其传递多个唯一列值时就是这种情况。


    在像您所做的那样运行了几个只传递唯一键值的测试之后,我发现了以下内容:

    1) 如果您的其他列包含一些值(不是默认值)并且您使用 REPLACE 语句传递唯一的键值,则设置所有其他列值到它们的 DEFAULT 值,因此受影响的行是 2。 REPLACE 删除现有行,因为该行包含您的 REPLACE 语句中未提及的值。

    来自文档的注释:

    所有列的值均取自 替换语句。任何缺少的列都设置为默认值 值,就像 INSERT 一样。

    2) 如果所有其他列值都是默认值,则使用 REPLACE 语句传递唯一的键值会导致 1。现在,1的原因我认为可能是以下之一:

    • 已进行更新(Update bar set foo=1 where foo=1 将在成功时返回 TRUE (1),尽管受影响的行将为 0)

    • REPLACE 永远不能返回 0(在 false 时返回 -1)

    所以基本上,你得到一个 1 因为你所有的其他列已经设置了默认值,如果你更改任何其他列的值并再次运行相同的语句,你会发现结果为 2

    【讨论】:

    • 谢谢你,但是我在我的问题中确实说过我的单列也是主键,所以我确实有一个 PK。无论如何,我的简单示例是我的实际用例的简化版本,它有更多的列。我只是想出了一个简单的例子来说明我的观点。
    猜你喜欢
    • 2015-10-30
    • 2011-03-15
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 2017-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多