AGGIORNA più tabelle in MySQL usando LEFT JOIN


165

Ho due tabelle e voglio aggiornare i campi in T1 per tutte le righe in un JOIN SINISTRA.

Per un semplice esempio, aggiorna tutte le righe del seguente set di risultati:

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

Il manuale di MySQL afferma che:

Le istruzioni UPDATE a più tabelle possono utilizzare qualsiasi tipo di join consentito nelle istruzioni SELECT, ad esempio LEFT JOIN.

Ma non riesco a trovare la sintassi corretta per farlo nell'aggiornamento AGGIORNATO di più tabelle.

Qual è la sintassi corretta?

Risposte:


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

Si noti che per un SELECTsarebbe più efficiente usare NOT IN/ NOT EXISTSsintassi:

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

Vedi l'articolo nel mio blog per i dettagli sulle prestazioni:

Sfortunatamente, MySQLnon consente l'uso della tabella di destinazione in una sottoquery in UPDATEun'istruzione, ecco perché è necessario attenersi a una LEFT JOINsintassi meno efficiente .


Non funziona in Oracle. Vedi questo post in quel caso.
Jon Ander,

Possiamo aggiungere un limite a questo? Come se volessi semplicemente aggiornare 10000 righe alla volta. Se aggiungo LIMIT 10000, mi viene visualizzato un errore che dice "Utilizzo errato di AGGIORNAMENTO e LIMITE"
Haril Satra,

28

Lo stesso può essere applicato a uno scenario in cui i dati sono stati normalizzati, ma ora si desidera che una tabella abbia valori trovati in una terza tabella. Quanto segue ti consentirà di aggiornare una tabella con le informazioni di una terza tabella che piace a una seconda tabella.

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;

Ciò sarebbe utile nel caso in cui avessi utenti e gruppi e volessi che un utente fosse in grado di aggiungere la propria variante del nome del gruppo, quindi in origine vorresti importare i nomi dei gruppi esistenti nel campo in cui si trova l'utente sarà in grado di modificarlo.


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  |

Aggiornerò il testo del campo nella tabella A con

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`

e arriva a questo risultato:

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

dove viene accettato solo un campo dalla tabella B, ma giungerò a questo risultato:

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

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`)
)

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

3
Aggiungi una spiegazione per rendere la risposta più utile!
namezero
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.