使用 LEFT JOIN 更新 MySQL 中的多个表
Posted
技术标签:
【中文标题】使用 LEFT JOIN 更新 MySQL 中的多个表【英文标题】:UPDATE multiple tables in MySQL using LEFT JOIN 【发布时间】:2010-10-22 20:31:46 【问题描述】:我有两个表,并且想为左连接中的所有行更新 T1 中的字段。
举个简单的例子,更新以下结果集的所有行:
SELECT T1.* FROM T1 LEFT JOIN T2 ON T1.id = T2.id WHERE T2.id IS NULL
mysql manual 声明:
多表 UPDATE 语句可以使用 SELECT 语句中允许的任何类型的连接,例如 LEFT JOIN。
但我在记录的多表更新中找不到正确的语法。
正确的语法是什么?
【问题讨论】:
【参考方案1】: 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)
【讨论】:
请添加说明,让答案更有用!【参考方案2】: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`)
)
【讨论】:
【参考方案3】: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 | |
+--------+--------------------------------------------+
【讨论】:
【参考方案4】:这同样适用于数据已被规范化的场景,但现在您希望一个表具有在第三个表中找到的值。以下将允许您使用第二个表喜欢的第三个表中的信息更新表。
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;
这在您有用户和组的情况下很有用,并且您希望用户能够添加自己的组名称变体,因此最初您希望将现有组名称导入到用户将能够对其进行修改。
【讨论】:
【参考方案5】: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
)
有关性能详情,请参阅我博客中的文章:
Finding incomplete orders:LEFT JOIN
与 NOT IN
相比的性能
不幸的是,MySQL
不允许在UPDATE
语句的子查询中使用目标表,这就是为什么您需要坚持使用效率较低的LEFT JOIN
语法。
【讨论】:
它在 Oracle 中不起作用。在这种情况下,请参阅此post。 我们可以为此添加限制吗?就像我想一次只更新 10000 行一样。如果我只添加 LIMIT 10000,它会给我一个错误,提示“错误使用 UPDATE 和 LIMIT”以上是关于使用 LEFT JOIN 更新 MySQL 中的多个表的主要内容,如果未能解决你的问题,请参考以下文章
关于mysql中的left join和left outer join的区别
使用 LEFT JOIN 的 MySQL 视图中的问题... GROUP BY
mysql update 的时候使用left join和where语句