使用 LEFTJOIN 更新 MySQL 中的多个表

我有两个表,希望更新 T1中左连接中所有行的字段。

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

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

MySQL 手册指出:

多表 UPDATE 语句可以使用 SELECT 语句中允许的任何类型的连接,例如 LEFTJOIN。

但是我找不到适当的语法来在文档化的多表 UPDATE 中完成这项工作。

正确的语法是什么?

289719 次浏览
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
)

有关性能细节,请参阅我博客中的文章:

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

同样的方法也可以应用于数据已经规范化的场景,但是现在您希望在第三个表中找到一个表的值。下面的代码允许您使用第二个表喜欢的第三个表中的信息更新表。

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)