METTRE À JOUR plusieurs tables dans MySQL en utilisant LEFT JOIN

165

J'ai deux tables et je veux mettre à jour les champs dans T1 pour toutes les lignes dans une jointure à gauche.

Pour un exemple simple, mettez à jour toutes les lignes de l'ensemble de résultats suivant:

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

Le manuel MySQL indique que:

Les instructions UPDATE à plusieurs tables peuvent utiliser n'importe quel type de jointure autorisé dans les instructions SELECT, telles que LEFT JOIN.

Mais je ne trouve pas la syntaxe appropriée pour cela dans la mise à jour documentée sur plusieurs tables.

Quelle est la syntaxe appropriée?

Paul Oyster
la source

Réponses:

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

Notez que pour un SELECTil serait plus efficace d'utiliser NOT IN/ NOT EXISTSsyntax:

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

Voir l'article de mon blog pour plus de détails sur les performances:

Malheureusement, MySQLn'autorise pas l'utilisation de la table cible dans une sous-requête dans une UPDATEinstruction, c'est pourquoi vous devrez vous en tenir à une LEFT JOINsyntaxe moins efficace .

Quassnoi
la source
Cela ne fonctionne pas dans Oracle. Voir cet article dans ce cas.
Jon Ander
Pouvons-nous ajouter une limite à cela? Comme je veux simplement mettre à jour 10000 lignes à la fois. Si j'ajoute simplement LIMIT 10000, cela me donne une erreur indiquant `` Utilisation incorrecte de UPDATE et LIMIT ''
Haril Satra
28

La même chose peut être appliquée à un scénario où les données ont été normalisées, mais vous voulez maintenant qu'une table ait des valeurs trouvées dans une troisième table. Ce qui suit vous permettra de mettre à jour une table avec des informations d'une troisième table qui est aimée par une deuxième table.

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;

Cela serait utile dans le cas où vous aviez des utilisateurs et des groupes et que vous souhaitiez qu'un utilisateur puisse ajouter sa propre variante du nom de groupe, donc à l'origine, vous voudriez importer les noms de groupe existants dans le champ où se trouve l'utilisateur va pouvoir le modifier.

les privilèges
la source
4
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  |

Je mettrai à jour le texte du champ dans le tableau A avec

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`

et venez à ce résultat:

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   |                        |
--------+-------------------------+

où un seul champ du tableau B est accepté, mais j'arriverai à ce résultat:

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   |                                            |
+--------+--------------------------------------------+
Dinesh Rabara
la source
0
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`)
)
client
la source
-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)
Shyam Sharma
la source
3
Veuillez ajouter une explication pour rendre la réponse plus utile!
namezero