Program Tip

데이터를 업데이트하는 SQL MERGE 문

programtip 2020. 12. 7. 20:36
반응형

데이터를 업데이트하는 SQL MERGE 문


이름이 지정된 데이터가있는 테이블이 있습니다. energydata

세 개의 열만 있습니다

(webmeterID, DateTime, kWh)

테이블에 새로운 업데이트 된 데이터 집합이 temp_energydata있습니다.

DateTimewebmeterID숙박 동일. 그러나 kWh값은 temp_energydata테이블 에서 업데이트해야 합니다.

올바른 방식으로 T-SQL을 작성하려면 어떻게해야합니까?


실제 SQL ServerMERGE이 필요하다고 가정합니다 .

MERGE INTO dbo.energydata WITH (HOLDLOCK) AS target
USING dbo.temp_energydata AS source
    ON target.webmeterID = source.webmeterID
    AND target.DateTime = source.DateTime
WHEN MATCHED THEN 
    UPDATE SET target.kWh = source.kWh
WHEN NOT MATCHED BY TARGET THEN
    INSERT (webmeterID, DateTime, kWh)
    VALUES (source.webmeterID, source.DateTime, source.kWh);

소스에없는 대상의 레코드도 삭제하려는 경우 :

MERGE INTO dbo.energydata WITH (HOLDLOCK) AS target
USING dbo.temp_energydata AS source
    ON target.webmeterID = source.webmeterID
    AND target.DateTime = source.DateTime
WHEN MATCHED THEN 
    UPDATE SET target.kWh = source.kWh
WHEN NOT MATCHED BY TARGET THEN
    INSERT (webmeterID, DateTime, kWh)
    VALUES (source.webmeterID, source.DateTime, source.kWh)
WHEN NOT MATCHED BY SOURCE THEN
    DELETE;

이것은 조금 더 인기가 있기 때문에주의해야 할 몇 가지주의 사항과 함께이 답변을 조금 확장해야한다고 생각합니다.

첫째, 이전 버전의 SQL Server에서 명령문의 동시성 문제MERGE 를보고하는 여러 블로그가 있습니다. 이 문제가 이후 버전에서 해결 된 적이 있는지 모르겠습니다. 어느 쪽이든 HOLDLOCK또는 SERIALIZABLE잠금 힌트를 지정하여 대부분 해결할 수 있습니다 .

MERGE INTO dbo.energydata WITH (HOLDLOCK) AS target
[...]

더 제한적인 트랜잭션 격리 수준으로 동일한 작업을 수행 할 수도 있습니다.

.NET에는 몇 가지 다른 알려진 문제MERGE있습니다. (Microsoft는 Connect를 망가 뜨리고 이전 시스템의 문제를 새 시스템의 문제와 연결하지 않았기 때문에 이러한 이전 문제를 추적하기가 어렵습니다. 감사합니다. Microsoft!) 제가 알 수 있듯이 대부분은 일반적이지 않습니다. 위와 동일한 잠금 힌트로 문제를 해결할 수 있지만 테스트하지는 않았습니다.

그렇기 때문에 제가 MERGE직접 진술에 문제가 없었지만 지금은 항상 WITH (HOLDLOCK)힌트를 사용하고 가장 간단한 경우에만 진술을 사용하는 것을 선호합니다.


구문을 외울 수 없기 때문에 종종 Bacon Bits 훌륭한 답변을 사용했습니다.

그러나 나는 보통 CTE를 추가로 추가하여 DELETE 부분을 더 유용하게 만듭니다. 왜냐하면 매우 자주 대상 테이블의 일부에만 병합을 적용하기를 원하기 때문입니다.

WITH target as (
    SELECT * FROM dbo.energydate WHERE DateTime > GETDATE()
)
MERGE INTO target WITH (HOLDLOCK)
USING dbo.temp_energydata AS source
    ON target.webmeterID = source.webmeterID
    AND target.DateTime = source.DateTime
WHEN MATCHED THEN 
    UPDATE SET target.kWh = source.kWh
WHEN NOT MATCHED BY TARGET THEN
    INSERT (webmeterID, DateTime, kWh)
    VALUES (source.webmeterID, source.DateTime, source.kWh)
WHEN NOT MATCHED BY SOURCE THEN
    DELETE

새 레코드가 포함되어 있지 않다고 가정하고의 energydata데이터 기반으로 레코드를 업데이트해야하는 경우 다음을 시도하십시오.temp_energydatatemp_enerydata

UPDATE e SET e.kWh = t.kWh
  FROM energydata e INNER JOIN 
       temp_energydata t ON e.webmeterID = t.webmeterID AND 
                            e.DateTime = t.DateTime

여기 sqlfiddle 이 작동 합니다.

But if temp_energydata contains new records and you need to insert it to energydata preferably with one statement then you should definitely go with the answer that Bacon Bits gave.


UPDATE ed
SET ed.kWh = ted.kWh
FROM energydata ed
INNER JOIN temp_energydata ted ON ted.webmeterID = ed.webmeterID

Update energydata set energydata.kWh = temp.kWh 
where energydata.webmeterID = (select webmeterID from temp_energydata as temp) 

THE CORRECT WAY IS :

UPDATE test1
INNER JOIN test2 ON (test1.id = test2.id)
SET test1.data = test2.data

참고URL : https://stackoverflow.com/questions/14806768/sql-merge-statement-to-update-data

반응형