LEFT JOIN kullanarak birden çok tabloyu MySQL'de GÜNCELLEME


165

İki tablo var ve bir LEFT JOIN tüm satırlar için T1 alanları güncelleştirmek istiyorum.

Kolay bir örnek için aşağıdaki sonuç kümesinin tüm satırlarını güncelleyin:

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

MySQL manuel devletler bu:

Birden çok tablo UPDATE deyimleri, LEFT JOIN gibi SELECT deyimlerinde izin verilen herhangi bir birleştirme türünü kullanabilir.

Ancak bunu belgelenmiş çoklu tablolar UPDATE yapmak için uygun sözdizimi bulamıyorum.

Doğru sözdizimi nedir?

Yanıtlar:


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

Bunun için / sözdizimini SELECTkullanmanın daha verimli olacağını unutmayın :NOT INNOT EXISTS

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

Performans ayrıntıları için blogumdaki makaleye bakın:

Ne yazık ki, MySQLhedef tablonun bir deyimdeki bir alt sorguda kullanılmasına izin vermez UPDATE, bu yüzden daha az verimli LEFT JOINsözdizimine bağlı kalmanız gerekir .


Oracle'da çalışmaz. Bu durumda bu gönderiye bakın .
Jon Ander

Buna bir sınır ekleyebilir miyiz? Sanki bir seferde 10000 satırı güncellemek istiyorum. Sadece LIMIT 10000
eklersem,

28

Aynı durum, verilerin normalleştirildiği bir senaryoya da uygulanabilir, ancak şimdi bir tablonun üçüncü bir tabloda bulunan değerlere sahip olmasını istiyorsunuz. Aşağıdakiler, bir tabloyu ikinci bir tablo tarafından sevilen üçüncü bir tablodaki bilgilerle güncellemenize olanak tanır.

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;

Bu, kullanıcılarınız ve gruplarınız olduğunda ve bir kullanıcının grup adı için kendi varyasyonlarını ekleyebilmesini istediğinizde faydalı olacaktır, bu nedenle başlangıçta mevcut grup adlarını kullanıcının bulunduğu alana aktarmak istersiniz. modifiye edebilecek.


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  |

Tablo A'daki alan metnini

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`

ve bu sonuca gelin:

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

Tablo B'den yalnızca bir alan kabul edilir, ancak bu sonuca geleceğim:

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
Cevabı daha kullanışlı hale getirmek için lütfen bir açıklama ekleyin!
namezero
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.