使用mysql 5.5,这样的语句:
update foo left join bar on foo.id=bar.id set foo.col='val', bar.col='val';
即使没有条形码,似乎也会更新foo行(并且bar.col =不会生成任何错误或警告)。但据我所知,这在mysql文档中并不能保证。
任何人都可以在SQL标准或Oracle中提供权威参考,说明这是故意的吗?
它在其他SQL版本中是否有效,特别是 postgres和 MariaDB,或其他版本的mysql?
请注意,与上述不同,以下内容确实将左连接提升为内连接:
update foo left join bar on foo.id=bar.id set bar.col='val';
但这可能只是一种优化。
更新:澄清一下,我看到的行为是我想要的行为;我只是担心在我看来没有证件。如果我想要一个内连接,我会使用一个。
答案 0 :(得分:2)
在PostgreSQL中,这种奇怪的语法简单无效。 UPDATE
statement只能直接更改单个表中的数据(除了继承)。
你会改用:
UPDATE foo
SET col = 'val'
FROM bar
WHERE foo.id = bar.id;
或者,由于您使用的是常量值,因此速度更快:
UPDATE foo
SET col = 'val'
WHERE EXISTS (
SELECT 1
FROM bar
WHERE foo.id = bar.id
);
..它应该在任何的命名RDMS(MySQL,SQL Server,Oracle,...)中工作。
这些查询中的任何一个仅更新foo
的行,其中bar
中找到匹配项。通常,添加以下内容是明智的:
AND col IS DISTINCT FROM 'val'
或者:
AND col <> 'val' -- if involved values are NOT NULL
..以避免空更新。
答案 1 :(得分:0)
这是一个左连接,所以你所看到的是预期的。
A cross join B
表示:每个A与每个B结合 - 就像笛卡尔积一样。
A inner join B
,或简称为A join B
,表示:每个A和B组合在一起,其中有一个A 和一个B - 如,必需同时拥有A和B 。
A left join B
表示:每个没有B的A,每个A和B组合在一个有A和B的地方 - 如, B可选。< / p>
A right join B
相当于B left join A
。
A full join B
表示:每个没有B的A,没有A的每个B,以及可以组合的每个A和B - 如A 和 B可选。
http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html
您的第二个查询会更新与第一个查询相同的bar
行。与第一个的唯一区别是您不再更新foo
,因此您可能看不到相同的受影响行数。您只是在关联bar
时才更新foo
,但请注意,该查询仍会追溯foo
与之无关联的bar
行。
回答问题的其他部分:是的,其他数据库引擎的行为方式相同,提供或采取与Erwin强调的语法相关的化妆品。更新语句的要点相当于伪代码,其类似于:for each row in (select … from …) do stuff
。 update table
中的表是关联的select … from … [join …]
语句中的第一个运行。