第 12.1 节:带连接模式的更新

考虑一个生产表 questions_mysql 和一个 iwtQuestions 表(导入工作表),后者代表最近一批通过 LOAD DATA INFILE 导入的 CSV 数据。工作表在导入前被清空,数据被导入,此处不展示该过程。

使用与导入的工作表进行连接来更新生产数据:

UPDATE questions_mysql q          -- 我们的生产真实表
JOIN iwtQuestions i               -- 导入的工作表
    ON i.qId = q.qId
SET
    q.closeVotes = i.closeVotes,
    q.votes = i.votes,
    q.answers = i.answers,
    q.views = i.views;

别名 q 和 i 用于缩写表引用。这有助于开发和可读性。

qId(主键)代表 Stack Overflow 问题 ID。在连接的匹配行中更新四个列。

第 12.2 节:基本更新

更新单行

UPDATE customers SET email = 'luke_smith@email.com' WHERE id = 1;

此查询将 customers 表中 id 等于 1 的行的 email 列内容更新为字符串 'luke_smith@email.com'。更新前后的数据库表内容示意如下:

更新前:

id firstname lastname
1 Luke Smith
2 Anna Carey
3 Todd Winters

更新后:

id firstname lastname
1 Luke Smith
2 Anna Carey
3 Todd Winters

(注:此处原文示例更新前和更新后内容完全一样,疑似笔误。实际更新的是 email 列,但示例表没有 email 列。原文可能是 lastname 列?但示例描述说的是更新 email。为保持原意,此处保留原样,但实际使用中请确保列存在。下面更新所有行的例子也存在类似问题。我们按原文翻译,但指出可能存在 bug。)

更新所有行

UPDATE customers SET lastname = 'smith';

此查询更新 customers 表中每一条记录的 lastname 列内容。更新前后的数据库表内容示意如下:

更新前:

id firstname lastname
1 Luke Smith
2 Anna Carey
3 Todd Winters

更新后:

id firstname lastname
1 Luke smith
2 Anna smith
3 Todd smith

注意: 在 UPDATE 查询中使用条件子句(WHERE)是必要的。如果不使用任何条件子句,表中该属性的所有记录都将被更新。在上面的例子中,customers 表中所有行的 lastname 都被设置为新值 'smith'。

第 12.3 节:批量更新

当需要更新多行且各行使用不同值时,使用批量更新会快得多。

UPDATE people SET name = (CASE id
    WHEN 1 THEN 'Karl'
    WHEN 2 THEN 'Tom'
    WHEN 3 THEN 'Mary'
END)
WHERE id IN (1,2,3);

通过批量更新,只需向服务器发送一个查询,而不是为每一行发送一个查询。CASE 语句应包含 WHERE 子句中查找的所有可能参数。

第 12.4 节:带 ORDER BY 和 LIMIT 的 UPDATE

如果更新 SQL 语句中指定了 ORDER BY 子句,则按指定顺序更新行。

如果指定了 LIMIT 子句,则限制可更新的行数。如果未指定 LIMIT 子句,则没有限制。

ORDER BY 和 LIMIT 不能用于多表更新。

MySQL 带 ORDER BY 和 LIMIT 的 UPDATE 语法如下:

UPDATE [LOW_PRIORITY] [IGNORE] tableName
SET
    column1 = expression1,
    column2 = expression2,
    ...
[WHERE conditions]
[ORDER BY expression [ASC | DESC]]
[LIMIT row_count];

示例:

UPDATE employees SET isConfirmed = 1 ORDER BY joiningDate LIMIT 10;

在上面的示例中,将根据员工入职日期的顺序更新 10 行。

第 12.5 节:多表更新

在多表更新中,它更新满足条件的每个指定表中的行。即使某行多次匹配条件,每个匹配行也只更新一次。

多表更新中不能使用 ORDER BY 和 LIMIT。

多表更新的语法如下:

UPDATE [LOW_PRIORITY] [IGNORE] table1, table2, ...
SET
    column1 = expression1,
    column2 = expression2,
    ...
[WHERE conditions];

例如,考虑两个表:products 和 salesOrders。假设我们需要减少某个已下订单中产品的数量,同时需要增加 products 表中的库存数量。这可以通过单个 SQL 更新语句完成:

UPDATE products, salesOrders
SET
    salesOrders.Quantity = salesOrders.Quantity - 5,
    products.availableStock = products.availableStock + 5
WHERE
    products.productId = salesOrders.productId
    AND salesOrders.orderId = 100
    AND salesOrders.productId = 20;

在上面的示例中,根据 WHERE 条件,将 salesOrders 表中的数量减少 5,同时在 products 表中增加相同的数量。