2009-04-30 5 views
145

두 개의 테이블이 있고 LEFT JOIN의 모든 행에 대해 T1의 필드를 업데이트하려고합니다.LEFT JOIN을 사용하여 MySQL의 여러 테이블을 업데이트하십시오.

다중 테이블 UPDATE 문에서 허용 조인의 모든 유형을 사용할 수 있습니다 다음과 같은 결과 집합의 쉬운 예를 들어

업데이트 모든 행 :

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

MySQL manual 상태 LEFT JOIN과 같은 SELECT 문

그러나 문서화 된 다중 테이블 업데이트에서이를 수행하기위한 적절한 구문을 찾을 수 없습니다.

올바른 구문은 무엇입니까? SELECT을 위해 사용하는 것이 더 효율적이 될 것이라고

답변

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

NOT IN/NOT EXISTS 구문 :

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

성능 자세한 내용은 내 블로그에있는 문서를 참조하십시오 :

불행히도 MySQLUPDATE 문에있는 하위 쿼리에서 대상 테이블을 사용할 수 없으므로 효율성이 낮은 LEFT JOIN 구문을 사용해야합니다.

+0

시도해 보았습니다. 'where ...'근처에서 구문 오류가 발생합니다. –

+1

물론입니다. 게시물 업데이트를 참조하십시오. – Quassnoi

+0

오라클에서는 작동하지 않습니다. 이 경우 [post] (http://stackoverflow.com/questions/2446764/oracle-update-statement-with-inner-join)를 참조하십시오. –

23

동일한 내용이 데이터가 정규화 된 시나리오에 적용될 수 있지만 이제는 테이블에 세 번째 테이블에있는 값이 있어야합니다. 다음은 두 번째 테이블이 선호하는 세 번째 테이블의 정보로 테이블을 업데이트 할 수 있습니다.

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 | 

나는

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` 

와 테이블 A에서 필드 텍스트를 업데이트하고이 결과에 올 것이다 :

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

이것은 작동하지 않을 수 있습니다. –

-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

답변을 더 유용하게 설명 해주십시오! – namezero

+0

을 올바르게 포맷하십시오. –

관련 문제