【问题标题】:Why does this UPDATE affect 2 rows when its WHERE specifies only one?当它的 WHERE 只指定一个时,为什么这个 UPDATE 会影响 2 行?
【发布时间】:2020-10-09 00:16:19
【问题描述】:

请对照Sakila 示例数据库检查我在 MySQL 8.0 中运行的以下 UPDATE 语句:

UPDATE `film`
SET
    `original_language_id` = FLOOR(1 + (RAND() * 6))
WHERE
    `film_id` = FLOOR(1 + (RAND() * 1000));

想法是从film 更新一个随机行,使该行的original_language_id 列键的值介于1 和6 之间。

film 表中有 1000 行,PK 从 1 到 1000。original_language_id 列是 language 表的外键。 language 表中有 6 行,PK 从 1 到 6。

MySQL 认为上述 UPDATE 语句不安全(错误 1175)。 (我很想知道为什么,但这不是我的问题)。所以为了强制语句运行,我在它前面加上:SET SQL_SAFE_UPDATES = 0;

当我运行我希望在输出窗口中看到的 UPDATE 语句时:

1 行受影响行匹配:1 更改:1 警告:0

但我有时会受到 0 行的影响,有时是 1 行,有时是 2 行!

我的问题是为什么这个 UPDATE 语句不始终影响一行且只影响一行?

PS - 请避免 cmets 关于查询是否对您有意义和/或谨慎禁用安全更新模式。该查询是用于学习目的的练习,我完全意识到所述模式的重要性。谢谢。

【问题讨论】:

  • “我很想知道原因,但这不是我的问题” 软件警告您查询不安全,但您故意忽略它并忽略了警告。然后你得到了意想不到的结果,想知道为什么?你应该关注警告!!!

标签: mysql sql random sql-update sql-order-by


【解决方案1】:

如果你想随机选择一行更新,那么你可以简单地使用order by rand()limit 1

update film
set original_language_id = floor(1 + (rand() * 6))
order by rand()
limit 1

这应该比使用连接的其他解决方案更有效 - 无论表中有多少行,它都可以工作(而您的原始方法要求您事先知道表中有多少行)

【讨论】:

    【解决方案2】:

    WHERE 子句:

    WHERE `film_id` = FLOOR(1 + (RAND() * 1000))
    

    对表的每一行执行,每次生成一个随机数并检查film_id列的值。
    所以有时会发生两个数字相等的情况,可以是 1,2 或多行,甚至没有。

    如果您只想更新 1 个随机行,您可以加入一个返回 1 个随机数的查询,如下所示:

    UPDATE `film` f
    INNER JOIN (SELECT FLOOR(1 + (RAND() * 1000)) rnd) t
    ON t.rnd = f.`film_id`
    SET `original_language_id` = FLOOR(1 + (RAND() * 6))
    

    【讨论】:

    • 注意。吹。您可能知道文档链接吗?这是否也适用于 SQL Server?
    • 据我所知这是 SQL 标准。
    • “where_condition 是一个表达式,对于要选择的每一行计算结果为真”(来源:dev.mysql.com/doc/refman/8.0/en/select.html
    • 你知道为什么 MySQL 将该语句归类为不安全吗?
    • 我认为这是因为您正在更新随机行,这被认为是不安全的,因为它可以更新表的所有行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-02
    • 1970-01-01
    • 2011-08-02
    • 1970-01-01
    • 2023-03-03
    • 2021-10-18
    相关资源
    最近更新 更多