使用LEFT JOIN在MySQL中更新多个表

我有两个表,并且想在LEFT JOIN中更新T1中所有行的字段。

举一个简单的例子,更新以下结果集的所有行:

SELECT T1.* FROM T1 LEFT JOIN T2 ON T1.id = T2.id WHERE T2.id IS NULL 

MySQL手册指出:

多表UPDATE语句可以使用SELECT语句中允许的任何types的连接,如LEFT JOIN。

但是我无法在logging的多表UPDATE中find正确的语法。

什么是正确的语法?

 UPDATE t1 LEFT JOIN t2 ON t2.id = t1.id SET t1.col1 = newvalue WHERE t2.id IS NULL 

请注意,对于SELECT ,使用NOT IN / NOT EXISTS语法会更有效:

 SELECT t1.* FROM t1 WHERE t1.id NOT IN ( SELECT id FROM t2 ) 

请参阅我博客中的文章以了解性能详情:

  • 查找不完整的订单 :执行LEFT JOINNOT IN相比

不幸的是, MySQL不允许在UPDATE语句的子查询中使用目标表,这就是为什么你需要坚持效率较低的LEFT JOIN语法。

同样的情况也适用于数据已经正常化的场景,但是现在你想让一个表在第三个表中find值。 以下将允许您使用第二个表所喜欢的第三个表中的信息来更新表。

 UPDATE t1 LEFT JOIN t2 ON t2.some_id = t1.some_id LEFT JOIN t3 ON t2.t3_id = t3.id SET t1.new_column = t3.column; 

这在有用户和组的情况下很有用,而且您希望用户能够添加自己的组名变体,所以最初您想要将现有组名称导入用户所在的字段将能够修改它。

 Table A +--------+-----------+ | A-num | text | | 1 | | | 2 | | | 3 | | | 4 | | | 5 | | +--------+-----------+ Table B +------+------+--------------+ | B-num| date | A-num | | 22 | 01.08.2003 | 2 | | 23 | 02.08.2003 | 2 | | 24 | 03.08.2003 | 1 | | 25 | 04.08.2003 | 4 | | 26 | 05.03.2003 | 4 | 

我将更新表A中的字段文本

 UPDATE `Table A`,`Table B` SET `Table A`.`text`=concat_ws('',`Table A`.`text`,`Table B`.`B-num`," from ",`Table B`.`date`,'/') WHERE `Table A`.`A-num` = `Table B`.`A-num` 

并得出这个结果:

 Table A +--------+------------------------+ | A-num | text | | 1 | 24 from 03 08 2003 / | | 2 | 22 from 01 08 2003 / | | 3 | | | 4 | 25 from 04 08 2003 / | | 5 | | --------+-------------------------+ 

表B中只有一个字段被接受,但我会得出这个结果:

 Table A +--------+--------------------------------------------+ | A-num | text | | 1 | 24 from 03 08 2003 | | 2 | 22 from 01 08 2003 / 23 from 02 08 2003 / | | 3 | | | 4 | 25 from 04 08 2003 / 26 from 05 03 2003 / | | 5 | | +--------+--------------------------------------------+ 
 UPDATE `Table A` a SET a.`text`=( SELECT group_concat(b.`B-num`,' from ',b.`date` SEPARATOR ' / ') FROM `Table B` b WHERE (a.`A-num`=b.`A-num`) ) 
  DECLARE @cols VARCHAR(max),@colsUpd VARCHAR(max), @query VARCHAR(max),@queryUpd VARCHAR(max), @subQuery VARCHAR(max) DECLARE @TableNameTest NVARCHAR(150) SET @TableNameTest = @TableName+ '_Staging'; SELECT @colsUpd = STUF ((SELECT DISTINCT '], T1.[' + name,']=T2.['+name+'' FROM sys.columns WHERE object_id = ( SELECT top 1 object_id FROM sys.objects WHERE name = ''+@TableNameTest+'' ) and name not in ('Action','Record_ID') FOR XML PATH('') ), 1, 2, '' ) + ']' Select @queryUpd ='Update T1 SET '+@colsUpd+' FROM '+@TableName+' T1 INNER JOIN '+@TableNameTest+' T2 ON T1.Record_ID = T2.Record_Id WHERE T2.[Action] = ''Modify''' EXEC (@queryUpd)