94

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

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

id字段是主要的。我怀疑以下查询应该需要几毫秒。

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 万行吗?还是我必须进行个别更新然后提交?

4

3 回答 3

192

试试这个

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)
于 2012-10-05T21:46:37.187 回答
7

如果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。

显然,上面的代码只有在id1、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。

于 2012-10-05T21:50:04.847 回答
5

那是因为你错过了 ELSE。

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

于 2012-10-05T21:51:48.573 回答