MEMPERBARUI beberapa tabel di MySQL menggunakan LEFT JOIN

165

Saya punya dua tabel, dan ingin memperbarui bidang di T1 untuk semua baris dalam BERGABUNG KIRI.

Sebagai contoh mudah, perbarui semua baris dari hasil-set berikut:

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

The pengguna MySQL menyatakan bahwa:

Pernyataan UPDATE multi-tabel dapat menggunakan semua tipe join yang diizinkan dalam pernyataan SELECT, seperti LEFT JOIN.

Tetapi saya tidak dapat menemukan sintaks yang tepat untuk melakukan hal itu dalam UPDATE multi-tabel yang didokumentasikan.

Apa sintaks yang tepat?

Paul Oyster
sumber

Jawaban:

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

Perhatikan bahwa untuk SELECTitu akan lebih efisien untuk menggunakan NOT IN/ NOT EXISTSsintaks:

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

Lihat artikel di blog saya untuk detail kinerja:

Sayangnya, MySQLtidak mengizinkan penggunaan tabel target dalam subquery dalam sebuah UPDATEpernyataan, itu sebabnya Anda harus tetap menggunakan LEFT JOINsintaks yang kurang efisien .

Quassnoi
sumber
Itu tidak berfungsi di Oracle. Lihat posting ini dalam kasus itu.
Jon Ander
Bisakah kita menambahkan batasan untuk ini? Seolah saya ingin memperbarui 10.000 baris sekaligus. Jika saya hanya menambahkan LIMIT 10000 itu memberi saya kesalahan mengatakan 'Penggunaan UPDATE dan LIMIT salah'
Haril Satra
28

Hal yang sama dapat diterapkan pada skenario di mana data telah dinormalisasi, tetapi sekarang Anda ingin tabel memiliki nilai yang ditemukan di tabel ketiga. Berikut ini akan memungkinkan Anda untuk memperbarui tabel dengan informasi dari tabel ketiga yang disukai oleh tabel kedua.

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;

Ini akan berguna dalam kasus di mana Anda memiliki pengguna dan grup, dan Anda ingin pengguna dapat menambahkan variasi sendiri dari nama grup, jadi awalnya Anda ingin mengimpor nama grup yang ada ke bidang di mana pengguna berada akan dapat memodifikasinya.

privasi
sumber
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  |

Saya akan memperbarui teks bidang dalam tabel A dengan

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`

dan sampai pada hasil ini:

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

di mana hanya satu bidang dari Tabel B diterima, tetapi saya akan sampai pada hasil ini:

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
sumber
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`)
)
tamu
sumber
-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
sumber
3
Silakan tambahkan penjelasan untuk membuat jawabannya lebih bermanfaat!
namezero