第 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 表中增加相同的数量。