SQL Server에서 JOIN으로 UPDATE 문을 어떻게 수행 할 수 있습니까?


1314

SQL Server 에서이 테이블을 '부모'테이블의 데이터 로 업데이트해야합니다 ( 아래 참조).

테이블 : 판매

id (int)
udid (int)
assid (int)

테이블 : ud

id  (int)
assid  (int)

sale.assid업데이트 할 올바른 값을 포함합니다 ud.assid.

어떤 쿼리를 수행합니까? 나는 생각하고 join있지만 가능 여부는 확실하지 않습니다.


3
어떤 RDBMS를 사용하고 있습니까? MySQL, SQL Server, Oracle, PostgreSQL 또는 다른 것?
Chris J

테이블 간의 관계는? 어떤 판매 기록이 ud의 기록과 일치하는지 어떻게 알 수 있습니까? 두 테이블 모두에서 기본 키로 id를 기반으로합니까?
Cătălin Pitiș '

UD를 어떻게 업데이트 할 수 있습니까? 그것은 단지 assid를 가지고 있으며 자신의 ID입니다. 존재하는 실제 값과 스크립트의 결과로 변경 또는 추가하려는 레코드와 관련하여 예를들 수 있습니까?
Bernhard Hofmann


답변:


2383

구문은 사용중인 SQL DBMS에 따라 다릅니다. 다음은 ANSI / ISO (일명 SQL DBMS에서 작동해야 함), MySQL, SQL Server 및 Oracle에서 수행하는 몇 가지 방법입니다. 필자가 제안한 ANSI / ISO 방법은 일반적으로 다른 두 방법보다 훨씬 느리지 만 MySQL, SQL Server 또는 Oracle 이외의 SQL DBMS를 사용하는 경우 갈 수있는 유일한 방법 일 수 있습니다 (예 : SQL DBMS가 지원하지 않는 경우 MERGE) :

ANSI / ISO :

update ud 
     set assid = (
          select sale.assid 
          from sale 
          where sale.udid = ud.id
     )
 where exists (
      select * 
      from sale 
      where sale.udid = ud.id
 );

MySQL :

update ud u
inner join sale s on
    u.id = s.udid
set u.assid = s.assid

SQL 서버 :

update u
set u.assid = s.assid
from ud u
    inner join sale s on
        u.id = s.udid

PostgreSQL :

update ud
  set assid = s.assid
from sale s 
where ud.id = s.udid;

FROMPostgres 절 에서 대상 테이블을 반복해서는 안됩니다 .

신탁:

update
    (select
        u.assid as new_assid,
        s.assid as old_assid
    from ud u
        inner join sale s on
            u.id = s.udid) up
set up.new_assid = up.old_assid

SQLite :

update ud 
     set assid = (
          select sale.assid 
          from sale 
          where sale.udid = ud.id
     )
 where RowID in (
      select RowID 
      from ud 
      where sale.udid = ud.id
 );

3
MySQL이 set assid = s.assid있어야한다고 생각 set u.assid = s.assid합니다.
dotancohen

2
ANSI 구문에서 SELECT 이후에 =두 개 이상의 행을 반환 하면 어떻게됩니까 ?
계정

2
@ ThrowawayAccount3Million 아마 실패했을 것입니다. AFAIK, 이러한 종류의 연산은 스칼라 값을 예상하고 대신 결과 세트가 제공되면 오류를 발생시킵니다.
프랜시스로드

6
OP가 테이블과 열에 대해 더 나은 이름을 선택하기를 바랍니다. 그것은 읽기 쉽고 직관적이지 않습니다.
S.Serpooshan

4
Postgre 9.3은 다음을 사용해서 만 작동했습니다update ud set assid = s.assid
StackUnder

143

이것은 SQL Server에서 작동합니다.

update ud 
set assid = sale.assid
from sale
where sale.udid = id

98

postgres

UPDATE table1
SET    COLUMN = value
FROM   table2,
       table3
WHERE  table1.column_id = table2.id
       AND table1.column_id = table3.id
       AND table1.COLUMN = value
       AND table2.COLUMN = value
       AND table3.COLUMN = value 

20
질문에 사용 된 테이블 / 열 이름을 사용하면 대답이 더 편리합니다. 답에 3 개의 표가있는 이유는 무엇입니까?
alfonx

50

표준 SQL 접근 방식은

UPDATE ud
SET assid = (SELECT assid FROM sale s WHERE ud.id=s.id)

SQL Server에서는 조인을 사용할 수 있습니다

UPDATE ud
SET assid = s.assid
FROM ud u
JOIN sale s ON u.id=s.id

1
첫 번째 열을 사용하면 2 열 이상에서 일치시킬 수 없지만 결합은 훌륭합니다.
makciook

6
@makciook : 응? WHERE추가 열에서 일치시키려는 경우 절에 조건을 추가 할 수 있습니다 .
siride

2
그냥 니트 ...하지만 OP는 sale.udid = ud.id를 의미한다고 생각합니다. 그리고 sale.id가 아닙니다.
Skippy VonDrake

39

PostgreSQL :

CREATE TABLE ud (id integer, assid integer);
CREATE TABLE sales (id integer, udid integer, assid integer);

UPDATE ud
SET assid = sales.assid
FROM sales
WHERE sales.id = ud.id;

26

JOIN -ing 다중 테이블을 사용한 단순화 된 업데이트 쿼리

   UPDATE
        first_table ft
        JOIN second_table st ON st.some_id = ft.some_id
        JOIN third_table tt  ON tt.some_id = st.some_id
        .....
    SET
        ft.some_column = some_value
    WHERE ft.some_column = 123456 AND st.some_column = 123456

참고 -first_table, second_table, third_table 및 123456과 같은 some_column은 데모 테이블 이름, 열 이름 및 ID입니다. 유효한 이름으로 바꾸십시오.


16

SQL을 실제로 이식 할 수없는 또 다른 예입니다.

MySQL의 경우 다음과 같습니다.

update ud, sale
set ud.assid = sale.assid
where sale.udid = ud.id;

자세한 내용은 여러 테이블 업데이트를 참조하십시오 . http://dev.mysql.com/doc/refman/5.0/en/update.html

UPDATE [LOW_PRIORITY] [IGNORE] table_references
    SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...
    [WHERE where_condition]

2
"SQL을 실제로 이식 할 수없는 이유"에 +1하십시오! 이식성은 매우 취약하여 변수를 선언하면 널리 사용되는 많은 데이터베이스 엔진에서 이식성이 손상됩니다.
Jeff Moden

8

Teradata Aster는 목표를 달성하는 또 다른 흥미로운 방법을 제공합니다.

MERGE INTO ud --what trable should be updated
USING sale -- from what table/relation update info should be taken
ON ud.id = sale.udid --join condition
WHEN MATCHED THEN 
    UPDATE SET ud.assid = sale.assid; -- how to update

8

최상위 게시물의 SQL-Server 중 하나는 T-SQL이지만 불행히도 Sybase에서는 작동하지 않을 것이라고 생각했습니다.

Sybase의 경우 업데이트가 별칭이 아닌 테이블 자체에 있어야한다는 것을 알았습니다.

update ud
set u.assid = s.assid
from ud u
    inner join sale s on
        u.id = s.udid

7

FROM 키워드를 사용하는 다음 명령문은 조인으로 여러 행을 업데이트하는 데 사용됩니다.

UPDATE users 
set users.DivisionId=divisions.DivisionId
from divisions join users on divisions.Name=users.Division

7

MySQL

where 절을 잊어 버리고 ON 조건에 모든 조건을 배치하면 최상의 성능을 얻을 수 있습니다.

쿼리가 먼저 테이블을 조인해야하고 where 절을 실행해야하기 때문에 조인하는 데 필요한 것을 줄이면 결과를 얻거나 udpate를 수행하는 가장 빠른 방법입니다.

대본

사용자 테이블이 있습니다. 사용자 이름이나 이메일 또는 account_number를 사용하여 로그인 할 수 있습니다. 이러한 계정은 활성 (1) 또는 비활성 (0) 일 수 있습니다. 이 테이블에는 50000 개의 행이 있습니다.

그런 다음 한 번에 사용하지 않도록 설정할 사용자 테이블이 있습니다. 그러나이 표에는 사용자 이름, 이메일 및 계정 번호가 혼합 된 하나의 열이 있습니다. 또한 "has_run"인디케이터가 있는데, 실행될 때 1 (true)로 설정해야합니다.

질문

UPDATE users User
    INNER JOIN
        blacklist_users BlacklistUser
        ON
        (
            User.username = BlacklistUser.account_ref
            OR
            User.email = BlacklistedUser.account_ref
            OR
            User.phone_number = BlacklistUser.account_ref
            AND
            User.is_active = 1
            AND
            BlacklistUser.has_run = 0
        )
    SET
        User.is_active = 0,
        BlacklistUser.has_run = 1;

추리

OR 조건 만 결합해야하는 경우 각 행을 4 번 확인하여 결합해야하는지 확인하고 더 많은 행을 리턴해야합니다. 그러나 더 많은 조건을 제공하면 참여할 때 모든 조건을 충족하지 않으면 많은 행을 "건너 뛸 수"있습니다.

보너스

더 읽기 쉽습니다. 모든 조건이 한 곳에 있고 업데이트 할 행이 한 곳에 있습니다


4

그리고 MS ACCESS에서 :

UPDATE ud 
INNER JOIN sale ON ud.id = sale.udid
SET ud.assid = sale.assid;

1
주의해서 SET는 레코드 세트 정의 직후에 와야합니다! 방금 WHERE 절이 필요한 Access 데이터베이스에서 비슷한 시나리오를 해결하려고했습니다 (유효한 ON 조건으로 허용하지 않음). 구문 오류를 피하기 위해 마지막에 와야했습니다.
Dodecaphone


3
UPDATE tblAppraisalBasicData
SET tblAppraisalBasicData.ISCbo=1
FROM tblAppraisalBasicData SI INNER JOIN  aaa_test RAN ON SI.EmpID = RAN.ID

3

이것을 시도하십시오, 나는 이것이 당신을 위해 일할 것이라고 생각합니다

update ud

set ud.assid = sale.assid

from ud 

Inner join sale on ud.id = sale.udid

where sale.udid is not null

2

SQLite의 경우 RowID 속성을 사용하여 업데이트하십시오.

update Table set column = 'NewValue'
where RowID = 
(select t1.RowID from Table t1
join Table2 t2 on t1.JoinField = t2.JoinField
where t2.SelectValue = 'FooMyBarPlease');

1
이것을 조금 설명해 주시겠습니까?
Mohammed Noureldin

1
@MohammedNoureldin 나는 설명하려고 노력할 것이다. 문제는 동일한 테이블을 사용하여 조인에 대한 쿼리 결과로 테이블을 업데이트하는 방법입니다. (sub-select) 문은 조인처럼 작동하며 시스템 필드 RowID를 반환합니다.이 필드는 테이블의 각 행에 대한 고유 번호입니다. 하위 선택은 여러 행을 반환 할 수 있으므로 "where RowID ="는 결과 하위 선택에서 올바른 단일 행을 선택하고 열을 업데이트합니다. 더 자세한 설명이 필요하거나이 주제에 대한 변형을 찾아야하는 경우 알려주십시오.
KeithTheBiped
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.