2009-04-30 45 views
145

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 một LEFT JOIN.CẬP NHẬT nhiều bảng trong MySQL bằng cách sử dụng LEFT JOIN

Đối với một ví dụ đơn giản, cập nhật tất cả các hàng của kết quả-set sau:

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

Các MySQL manual bang rằng:

Nhiều-bảng câu lệnh UPDATE có thể sử dụng bất kỳ loại join phép trong Các câu lệnh SELECT, chẳng hạn như LEFT JOIN.

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 UPDATE nhiều bảng được lập tài liệu.

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

Trả lời

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

Lưu ý rằng đối với một SELECT nó sẽ hiệu quả hơn để sử dụng NOT IN/NOT EXISTS cú pháp:

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 thực hiện:

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

+0

Đã thử điều đó. Nó đưa ra một lỗi cú pháp gần 'ở đâu ...'. –

+1

Chắc chắn. Xem cập nhật bài đăng. – Quassnoi

+0

Nó không hoạt động trong Oracle. Xem [post] này (http://stackoverflow.com/questions/2446764/oracle-update-statement-with-inner-join) trong trường hợp đó. –

23

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

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; 

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 có một người sử dụng có thể thêm biến thể riêng của họ về tên nhóm, vì vậy ban đầu bạn sẽ muốn nhập tên nhóm hiện có vào trường nơi 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 nội dung lĩnh vực 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 |      | 
--------+-------------------------+ 

mà chỉ có một trường từ Bảng B được chấp nhận, nhưng tôi sẽ đến với 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`) 
) 
+0

Điều này có thể không hoạt động. –

-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 = ''[email protected]+'' 
            ) 
       and name not in ('Action','Record_ID') 
       FOR XML PATH('') 
      ), 1, 2, '' 
     ) + ']' 


    Select @queryUpd ='Update T1 
SET '[email protected]+' 
FROM '[email protected]+' T1 
INNER JOIN '[email protected]+' T2 
ON T1.Record_ID = T2.Record_Id 
WHERE T2.[Action] = ''Modify''' 
EXEC (@queryUpd) 
+3

Vui lòng thêm giải thích để làm cho câu trả lời hữu ích hơn! – namezero

+0

và định dạng đúng –

Các vấn đề liên quan