CẬP NHẬT nhiều bảng trong MySQL bằng LEFT THAM GIA


165

Tôi có hai bảng và muốn cập nhật các trường trong T1 cho tất cả các hàng trong THAM GIA TRÁI.

Để có một ví dụ dễ dàng, hãy cập nhật tất cả các hàng của tập kết quả sau:

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

Các dẫn sử dụng MySQL bang rằng:

Các câu lệnh CẬP NHẬT nhiều bảng có thể sử dụng bất kỳ loại tham gia nào được phép trong các câu lệnh CHỌN, chẳng hạn như TRÁI PHIẾU.

Nhưng tôi không thể tìm thấy cú pháp thích hợp để thực hiện điều đó trong CẬP NHẬT nhiều bảng.

Cú pháp thích hợp là gì?

Câu trả lời:


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

Lưu ý rằng SELECTđể sử dụng NOT IN/ NOT EXISTScú pháp sẽ hiệu quả hơn :

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

Xem bài viết trong blog của tôi để biết chi tiết hiệu suất:

Thật không may, MySQLkhông cho phép sử dụng bảng mục tiêu trong truy vấn con trong một UPDATEcâu lệnh, đó là lý do tại sao bạn cần phải sử dụng LEFT JOINcú pháp kém hiệu quả hơn .


Nó không hoạt động trong Oracle. Xem bài này trong trường hợp đó.
Jon Ander

Chúng ta có thể thêm một giới hạn cho điều này? Giống như tôi muốn chỉ cập nhật 10000 hàng cùng một lúc. Nếu tôi chỉ thêm LIMIT 10000, nó sẽ báo lỗi 'Sử dụng CẬP NHẬT và
GIỚI

28

Điều tương tự có thể được áp dụng cho một kịch bản trong đó dữ liệu đã được chuẩn hóa, nhưng bây giờ bạn muốn một bảng có các giá trị được tìm thấy trong bảng thứ ba. Sau đây sẽ cho phép bạn cập nhật một bảng với thông tin từ bảng thứ ba được yêu thích bởi bảng thứ hai.

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;

Điều này sẽ hữu ích trong trường hợp bạn có người dùng và nhóm và bạn muốn người dùng có thể thêm biến thể tên nhóm của riêng họ, vì vậy ban đầu bạn sẽ muốn nhập tên nhóm hiện có vào trường có người dùng sẽ có thể sửa đổi nó.


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  |

Tôi sẽ cập nhật văn bản trường trong bảng A với

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`

và đi đến kết quả này:

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

trong đó chỉ có một trường từ Bảng B được chấp nhận, nhưng tôi sẽ đi đến kết quả này:

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
Vui lòng thêm một lời giải thích để làm cho câu trả lời hữu ích hơn!
namezero
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.