所以我遇到了一个奇怪的情况,并不像我期望的那样表现得很好。带一对多连接的更新语句
比方说,我有如下表:
DROP TABLE IF EXISTS test;
CREATE TABLE test (somekey char(1) PRIMARY KEY, value1 int, value2 int);
INSERT INTO test VALUES
("a", 1, 1),
("b", 2, 2),
("c", 3, 3);
DROP TABLE IF EXISTS test2;
CREATE TABLE test2 (somekey char(1), thing int, value int);
INSERT INTO test2 VALUES
("a", 100, 10),
("a", 200, 10),
("b", 100, 20),
("b", 200, 20),
("c", 100, 30),
("c", 200, 30);
,现在我想基于test2
更新test
:
UPDATE
test AS t
JOIN test2 AS t2
ON t.somekey = t2.somekey
SET
t.value1 = IF(t2.thing = 100, t2.value, t.value1),
t.value2 = IF(t2.thing = 200, t2.value, t.value2);
这是我的输出:
SELECT * FROM test;
+---------+--------+--------+
| somekey | value1 | value2 |
+---------+--------+--------+
| a | 10 | 1 |
| b | 20 | 2 |
| c | 30 | 3 |
+---------+--------+--------+
对于某些原因,value2
未更新。
我发现如果我改变test2
,使得200在100之前插入,则会发生完全相反的情况。这使我相信MySQL实际上是由somekey
组成的,并且完全忽略了test2
中的一半行。但是,如果我执行的是完全相同的连接,并基于test
更新test2
中的某些内容,则不会执行分组,test2
中的所有六行都会更新。
简单的解决方法是简单的加盟test2
两次,像这样:
UPDATE
test AS t
JOIN test2 AS t100
ON t100.somekey = t.somekey
AND t100.thing = 100
JOIN test2 AS t200
ON t200.somekey = t.somekey
AND t200.thing = 200
SET
t.value1 = t100.value,
t.value2 = t200.value;
,但我不觉得我应该做这种方式。第一次更新有什么问题?为什么MySQL的行为如此呢?
啊,谢谢你在文档中发现。至少它似乎是有意的行为。 –