我怎样才能简化这些查询
UPDATE `table` SET `col1` = 'abc', `col2` = 'xyz' WHERE `col3` = '1';
UPDATE `elbat` SET `col1` = `a`, `col2` = 'x' WHERE `col3` = '1';
UPDATE `elbat` SET `col1` = `b`, `col2` = 'y' WHERE `col3` = '2';
UPDATE `elbat` SET `col1` = `c`, `col2` = 'z' WHERE `col3` = '3';
Run Code Online (Sandbox Code Playgroud)
进入这样的事情?
UPDATE `table` a, `elbat` b
SET a.`col1` = 'abc', a.`col2` = 'xyz' WHERE a.`col3` = '1',
SET b.`col1` = `a`, b.`col2` = 'x' WHERE b.`col3` = '1',
SET b.`col1` = `b`, b.`col2` = 'y' WHERE b.`col3` = '2',
SET b.`col1` = `c`, b.`col2` = 'z' WHERE b.`col3` = '3';
Run Code Online (Sandbox Code Playgroud)
运行单查询而不是四查询
可以根据某些条件更新行。还可以在 MySQL 中的一条语句中更新多个表。
不过,后者是否是一个好主意还有待商榷。目标表将连接在一起进行更新,当我说“连接”时,我的意思是更广泛的含义:您不必指定连接条件,在这种情况下,它们将是交叉连接。在交叉联接中,当至少一个表具有多于一行时,另一个表将不可避免地在联接集中出现重复的行。如果两者都有多行,则两者都会将它们相乘。有点违反直觉,MySQL 仍然只会更新每个受影响的行一次,但在这种情况下我会避免进行多表更新,即使仅仅是因为违反直觉。
无论如何,继续您的具体示例,确实没有连接条件,每个表上只有一个过滤器。您可以在 UPDATE 的 WHERE 子句中指定这些过滤器。现在,为了选择更新每列的值,您可以使用 CASE 表达式。完整的 UPDATE 语句可能如下所示:
UPDATE
A, B
SET
A.col1 = 'abc',
A.col2 = 'xyz',
B.col1 = CASE B.col3
WHEN '1' THEN 'a'
WHEN '2' THEN 'b'
WHEN '3' THEN 'c'
END,
B.col2 = CASE B.col3
WHEN '1' THEN 'x'
WHEN '2' THEN 'y'
WHEN '3' THEN 'z'
END
WHERE
A.col3 = '1'
AND B.col3 IN ('1', '2', '3')
;
Run Code Online (Sandbox Code Playgroud)
您可以看到,您必须在 CASE 表达式中为 forB.col1和 for重复相同的条件集B.col2。有办法避免这种情况吗?
就在这里。B.col1您可以将和 的目标值B.col2以及过滤值排列为B.col3派生表,并将其连接到BUPDATE 子句中,如下所示:
UPDATE
A,
B
INNER JOIN
(
SELECT 'a' AS col1, 'x' AS col2, '1' AS col3
UNION ALL
SELECT 'b', 'y', '2'
UNION ALL
SELECT 'c', 'z', '3'
) AS fltr ON B.col3 = fltr.col3
SET
A.col1 = 'abc',
A.col2 = 'xyz',
B.col1 = fltr.col1,
B.col2 = fltr.col2
WHERE
A.col3 = '1'
;
Run Code Online (Sandbox Code Playgroud)
连接还充当 的过滤器B,因此您可以省略 WHERE 子句中的过滤器。
您可以在以下位置找到每种方法的演示:
数据库<>小提琴:
最后,正如本文开头和评论中所述,您可以为每个表使用单独的 UPDATE 语句。对于脚本的读者和数据库引擎来说,结果的意图都是明确的。更简单的脚本使后者能够有更多的优化选项。
使用上述任一方法进行表B更新,但分别执行两个表:
UPDATE
A
SET
A.col1 = 'abc',
A.col2 = 'xyz'
WHERE
A.col3 = '1'
;
Run Code Online (Sandbox Code Playgroud)
UPDATE
B
INNER JOIN
(
SELECT 'a' AS col1, 'x' AS col2, '1' AS col3
UNION ALL
SELECT 'b', 'y', '2'
UNION ALL
SELECT 'c', 'z', '3'
) AS fltr ON B.col3 = fltr.col3
SET
B.col1 = fltr.col1,
B.col2 = fltr.col2
;
Run Code Online (Sandbox Code Playgroud)
将更新拆分为单独的语句还有另一个原因。由于对于单个 UPDATE 语句需要连接表,因此两个表都有要更新的行非常重要。如果一个表没有匹配的行,那么即使另一个表有,也不会更新。这是因为与非空集交叉连接的空集仍然会产生空集。
因此,如果至少一个表没有与条件匹配的行,则单个 UPDATE 语句将没有行可处理。单独的 UPDATE 不会发生这种情况,因为每个表都将使用自己的表,而不管另一个表的内容如何,因此,一个表中缺少行不会影响另一个表的更新。
| 归档时间: |
|
| 查看次数: |
32931 次 |
| 最近记录: |