อัปเดตหลายตารางใน MySQL โดยใช้ LEFT JOIN


165

ฉันมีสองตารางและต้องการอัปเดตเขตข้อมูลใน T1 สำหรับแถวทั้งหมดใน LEFT JOIN

สำหรับตัวอย่างง่ายๆอัปเดตแถวทั้งหมดของชุดผลลัพธ์ต่อไปนี้:

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

MySQL คู่มือระบุว่า:

คำสั่ง UPDATE หลายตารางสามารถใช้การเข้าร่วมประเภทใดก็ได้ในคำสั่ง SELECT เช่น LEFT JOIN

แต่ฉันไม่พบไวยากรณ์ที่เหมาะสมสำหรับการทำเช่นนั้นใน UPDATE หลายตารางที่ทำเป็นเอกสาร

ไวยากรณ์ที่เหมาะสมคืออะไร?

คำตอบ:


318
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 ดูโพสต์นี้ในกรณีนั้น
Jon Ander

เราสามารถเพิ่มขีด จำกัด นี้ได้หรือไม่? เช่นฉันต้องการเพียงแค่อัปเดต 10,000 แถวในแต่ละครั้ง ถ้าฉันเพิ่งเพิ่ม LIMIT 10000 มันทำให้ฉันมีข้อผิดพลาดที่บอกว่า 'การใช้งาน UPDATE และ LIMIT ไม่ถูกต้อง'
Haril Satra

28

เดียวกันสามารถนำไปใช้กับสถานการณ์ที่ข้อมูลได้รับการทำให้เป็นมาตรฐาน แต่ตอนนี้คุณต้องการให้ตารางมีค่าที่พบในตารางที่สาม ต่อไปนี้จะช่วยให้คุณอัปเดตตารางด้วยข้อมูลจากตารางที่สามที่ชอบโดยตารางที่สอง

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;

สิ่งนี้จะมีประโยชน์ในกรณีที่คุณมีผู้ใช้และกลุ่มและคุณต้องการให้ผู้ใช้สามารถเพิ่มรูปแบบชื่อกลุ่มของตนเองได้ แต่เดิมคุณต้องการนำเข้าชื่อกลุ่มที่มีอยู่ในฟิลด์ที่ผู้ใช้อยู่ จะสามารถแก้ไขได้


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  |

ฉันจะอัปเดตข้อความฟิลด์ในตาราง 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   |                                            |
+--------+--------------------------------------------+


-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
โปรดเพิ่มคำอธิบายเพื่อให้คำตอบมีประโยชน์มากขึ้น!
namezero
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.