【问题标题】:MySQL update CASE WHEN/THEN/ELSE [duplicate]MySQL 更新 CASE WHEN/THEN/ELSE [重复]
【发布时间】:2020-11-14 15:24:46
【问题描述】:

我正在尝试使用 CLI 脚本更新 LARGE MyISAM 表(2500 万条记录)。该表没有被其他任何东西锁定/使用。

我认为与其对每条记录执行单个 UPDATE 查询,不如利用 CASE 功能。

id 字段是 PRIMARY。我怀疑以下查询需要几毫秒。

UPDATE `table` SET `uid` = CASE
    WHEN id = 1 THEN 2952
    WHEN id = 2 THEN 4925
    WHEN id = 3 THEN 1592
    END

你瞧,查询占用了 CPU 并且不会永远完成。

然后,令我惊讶的是,我发现查询正在更新所有 2500 万行,在我没有指定的行上放置了一个 NULL。

这样做的目的是什么?我可以在每次执行此查询时只对特定行进行 MASS 更新而不更新 2500 万行吗?还是我必须进行个别更新然后提交?

【问题讨论】:

  • 当您在case 语句中未指定else 时,默认为null
  • 只需放置一个过滤器 where 子句

标签: mysql


【解决方案1】:

试试这个

UPDATE `table` SET `uid` = CASE
    WHEN id = 1 THEN 2952
    WHEN id = 2 THEN 4925
    WHEN id = 3 THEN 1592
    ELSE `uid`
    END
WHERE id  in (1,2,3)

【讨论】:

  • 纯代码答案在 Stack Overflow 上的价值很低,因为它们对教育/授权成千上万的未来研究人员几乎没有作用。如果逻辑上无法到达,为什么还要写ELSE
  • @mickmackusa 添加一个 else 有利于防止代码更改时发生意外,例如实施者将更改 WHERE 子句。这类似于在return 语句之后将无法访问的break;s 添加到switch-case 语句。关于仅代码的答案,我同意。回答者本可以提供有关代码背后推理的更多详细信息。
【解决方案2】:

如果id 从 1 开始顺序排列,那么最简单(也是最快)的方法是:

UPDATE `table` 
SET uid = ELT(id, 2952, 4925, 1592) 
WHERE id IN (1,2,3)

ELT() 返回字符串列表的第 N 个元素:如果 N = 1,则返回 str1,如果 N = 2,则返回 str2,依此类推。如果 N 小于 1 或大于参数个数,则返回 NULL。

显然,上述代码仅在 id 为 1、2 或 3 时有效。如果 id 为 10、20 或 30,则以下任一方法都有效:

UPDATE `table` 
SET uid = CASE id 
WHEN 10 THEN 2952 
WHEN 20 THEN 4925 
WHEN 30 THEN 1592 END CASE 
WHERE id IN (10, 20, 30)

或更简单的:

UPDATE `table` 
SET uid = ELT(FIELD(id, 10, 20, 30), 2952, 4925, 1592) 
WHERE id IN (10, 20, 30)

作为FIELD(),返回str在str1、str2、str3、...列表中的索引(位置)。如果未找到 str,则返回 0。

【讨论】:

  • 只有当 uid 确实是 1、2、3 时,您的“更简单”版本才有效。(来源:dev.mysql.com/doc/refman/5.0/en/…
  • 我将它与FIELD 结合起来,例如UPDATE table SET uid = ELT(FIELD(id, 1,2,3), 2952, 4925, 1592) WHERE id IN (1,2,3)
  • 更简单的想法是否来自this comment BringerOfTheDawn 声明“我将其与FIELD 结合在一起,例如UPDATE table SET uid = ELT(FIELD(id, 1,2,3), 2952, 4925, 1592) WHERE id IN (1,2,3)”?
【解决方案3】:

那是因为你错过了 ELSE。

"返回第一个条件为真的结果。如果没有匹配的结果值,则返回 ELSE 之后的结果,如果没有 ELSE 部分,则返回 NULL。 (http://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html#operator_case)

【讨论】:

  • 即使我指定了 ELSE.. 它不会尝试更新其余部分吗?当我只需要更新3条时,我仍然不想更新2500万条记录。放置WHERE子句解决了问题。
  • 这个答案可以解决问题,但不能以高效/直接/最佳实践的方式解决。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-15
  • 1970-01-01
相关资源
最近更新 更多