【问题标题】:UPDATE multiple tables in MySQL using LEFT JOIN使用 LEFT JOIN 更新 MySQL 中的多个表
【发布时间】: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。

但我在记录的多表更新中找不到正确的语法。

正确的语法是什么?

【问题讨论】:

    标签: mysql sql-update


    【解决方案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
                  )
          

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

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

          【讨论】:

          • 它在 Oracle 中不起作用。在这种情况下,请参阅此post
          • 我们可以为此添加限制吗?就像我想一次只更新 10000 行一样。如果我只添加 LIMIT 10000,它会给我一个错误,提示“错误使用 UPDATE 和 LIMIT”
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-19
          • 1970-01-01
          • 2013-05-14
          • 1970-01-01
          • 1970-01-01
          • 2012-06-21
          相关资源
          最近更新 更多