featur

[MSSQL] MERGE를 사용하여 INSERT,UPDATE,DELETE 한번에 본문

개발/MSSQL

[MSSQL] MERGE를 사용하여 INSERT,UPDATE,DELETE 한번에

featur 2016. 12. 20. 10:11


[MSSQL] MERGE를 사용하여 INSERT,UPDATE,DELETE 한번에




SQL Server 2008에서는 MERGE 문을 사용하여 단일 문에서 삽입, 업데이트 또는 삭제 작업을 수행할 수 있습니다. MERGE 문을 사용하면 대상 테이블 또는 뷰와 데이터 원본을 조인한 다음 이 조인의 결과를 바탕으로 대상에 대해 여러 동작을 수행할 수 있습니다. 예를 들어 MERGE 문을 사용하여 다음과 같은 작업을 수행할 수 있습니다.

  • 대상 테이블에서 조건에 따라 행을 삽입 또는 업데이트합니다.

    대상 테이블에 행이 존재하는 경우 하나 이상의 열을 업데이트하고, 그렇지 않으면 새 행에 데이터를 삽입합니다.

  • 두 테이블을 동기화합니다.

    원본 데이터와의 차이점에 따라 대상 테이블에서 행을 삽입, 업데이트 또는 삭제합니다.

MERGE 구문은 다음과 같은 5개의 기본 절로 구성됩니다.

  • MERGE 절은 삽입, 업데이트 또는 삭제 작업의 대상인 테이블 또는 뷰를 지정합니다.

  • USING 절은 대상과 조인되는 데이터 원본을 지정합니다.

  • ON 절은 대상과 원본이 일치하는 부분을 확인하는 조인 조건을 지정합니다.

  • WHEN 절(WHEN MATCHED, WHEN NOT MATCHED BY TARGET 및 WHEN NOT MATCHED BY SOURCE)은 WHEN 절에 지정된 추가 검색 조건 및 ON 절의 결과를 바탕으로 수행할 동작을 지정합니다.

  • OUTPUT 절은 대상에서 삽입, 업데이트 또는 삭제된 각 행에 대해 한 행을 반환합니다.



원본 및 대상 검색 조건 지정




원본 데이터와 대상 데이터가 하나의 입력 스트림으로 병합되는 방법, 그리고 추가 검색 조건을 사용하여 불필요한 행을 올바르게 필터링하는 방법을 이해해야 합니다. 이 부분을 이해하지 못하면 추가 검색 조건을 잘못 지정할 수 있고 이로 인해 부정확한 결과가 발생하게 됩니다.

원본의 행은 ON 절에 지정된 조인 조건자를 기준으로 대상의 행과 비교됩니다. 결과는 조합된 입력 스트림입니다. 입력 행당 하나의 삽입, 업데이트 또는 삭제 작업이 수행됩니다. 문에 지정된 WHEN 절에 따라 입력 행은 다음 중 하나일 수 있습니다.

  • 대상과 원본에서 각각 하나씩의 행으로 구성된 일치하는 쌍. WHEN MATCHED 절의 결과입니다.

  • 해당하는 행이 대상에 없는 원본의 행. WHEN NOT MATCHED BY TARGET 절의 결과입니다.

  • 해당하는 행이 원본에 없는 대상의 행. WHEN NOT MATCHED BY SOURCE 절의 결과입니다.

MERGE 문에 지정되는 WHEN 절의 조합은 쿼리 프로세서에 의해 구현되는 조인 유형을 결정하고 결과 입력 스트림에 영향을 줍니다. 예를 들어 다음과 같은 원본 및 대상 테이블과 데이터의 예를 살펴보겠습니다.


 


USE tempdb;

GO

CREATE TABLE dbo.Target(EmployeeID int, EmployeeName varchar(10), 

     CONSTRAINT Target_PK PRIMARY KEY(EmployeeID));

CREATE TABLE dbo.Source(EmployeeID int, EmployeeName varchar(10), 

     CONSTRAINT Source_PK PRIMARY KEY(EmployeeID));

GO

INSERT dbo.Target(EmployeeID, EmployeeName) VALUES(100, 'Mary');

INSERT dbo.Target(EmployeeID, EmployeeName) VALUES(101, 'Sara');

INSERT dbo.Target(EmployeeID, EmployeeName) VALUES(102, 'Stefano');


GO

INSERT dbo.Source(EmployeeID, EmployeeName) Values(103, 'Bob');

INSERT dbo.Source(EmployeeID, EmployeeName) Values(104, 'Steve');

GO





다음 표에서는 가능한 조인 유형을 나열하고 각 유형이 쿼리 최적화 프로그램에 의해 구현되는 시점을 보여 줍니다. 또한 이 표에서는 원본 및 대상 데이터를 비교하기 위한 검색 조건이 Source.EmployeeID = Target.EmployeeID인 경우 원본 및 대상 테이블 예의 결과 입력 스트림도 보여 줍니다.


조인 유형

구현

예 입력 스트림 결과

INNER JOIN

WHEN 절로는 WHEN MATCHED 절만 지정됩니다.

SrcEmpID SrcName TrgEmpID TrgName

-------- ------- -------- -------

NULL     NULL    NULL     NULL

LEFT OUTER JOIN

WHEN NOT MATCHED BY TARGET 절은 지정되지만 WHEN NOT MATCHED BY SOURCE 절은 지정되지 않습니다. WHEN MATCHED는 지정될 수도 있고 지정되지 않을 수도 있습니다.

SrcEmpID SrcName TrgEmpID TrgName

-------- ------- -------- -------100      Mary    NULL     NULL

101      Sara    NULL     NULL

102      Stefano NULL     NULL

RIGHT OUTER JOIN

WHEN MATCHED 절과 WHEN NOT MATCHED BY SOURCE 절은 지정되지만 WHEN NOT MATCHED BY TARGET 절은 지정되지 않습니다.

SrcEmpID SrcName TrgEmpID TrgName

-------- ------- -------- -------NULL     NULL    103      Bob

NULL     NULL    104      Steve

FULL OUTER JOIN

WHEN NOT MATCHED BY TARGET 절과 WHEN NOT MATCHED BY SOURCE 절이 지정됩니다. WHEN MATCHED는 지정될 수도 있고 지정되지 않을 수도 있습니다.

SrcEmpID SrcName TrgEmpID TrgName

-------- ------- -------- -------100      Mary    NULL     NULL

101      Sara    NULL     NULL

102      Stefano NULL     NULL

NULL     NULL    103      Bob

NULL     NULL    104      Steve

ANTI SEMI JOIN

WHEN 절로는 WHEN NOT MATCHED BY SOURCE 절만 지정됩니다.

TrgEmpID TrgName

-------- -------

100      Mary

101      Sara

102      Stefano


입력 스트림 결과 예는 입력 스트림 결과가 WHEN 절의 조합에 따라 달라진다는 사실을 보여 줍니다. 이제 이 입력 스트림을 기반으로 대상 테이블에 다음과 같은 동작을 수행하려는 경우를 가정해 보겠습니다.
  • 직원 ID가 대상 테이블에 없고 원본 직원 이름이 'S’로 시작하는 경우 원본 테이블의 행을 삽입합니다.

  • 대상 직원 이름이 'S'로 시작하고 원본 테이블에 직원 ID가 없는 경우 대상 테이블의 행을 삭제합니다.

이러한 동작을 수행하려면 다음 WHEN 절이 필요합니다.

  • WHEN NOT MATCHED BY TARGET THEN INSERT

  • WHEN NOT MATCHED BY SOURCE THEN DELETE

이전 표에 설명되어 있듯이 두 개의 WHEN NOT MATCHED 절이 모두 지정된 경우 결과 입력 스트림은 원본 및 대상 테이블의 완전 외부 조인이 됩니다. 이제 입력 스트림 결과를 알고 있으므로 삽입, 업데이트 및 삭제 동작을 입력 스트림에 적용하는 방법을 고려해야 합니다.

앞서 언급했듯이 WHEN 절은 WHEN 절에 지정된 추가 검색 조건 및 ON 절의 결과를 기준으로 수행할 동작을 지정합니다. 

많은 경우 ON 절에 지정된 검색 조건으로 필요한 입력 스트림을 생성합니다. 그러나 여기에 사용된 예 시나리오의 경우 삽입 및 삭제 동작을 위해서는 'S’로 시작하는 직원 이름을 가진 행만 영향을 받도록 제한하는 추가 필터링이 필요합니다. 

다음 예에서 필터링 조건은 WHEN NOT MATCHED BY TARGET 및 HEN NOT MATCHED BY SOURCE에 적용됩니다. 문의 결과에서는 입력 스트림의 원하는 행이 수정, 삽입 및 삭제되었음을 볼 수 있습니다.




-- MERGE statement with the join conditions specified correctly.

USE tempdb;

GO

BEGIN TRAN;

MERGE Target AS T

USING Source AS S

ON (T.EmployeeID = S.EmployeeID) 

WHEN NOT MATCHED BY TARGET AND S.EmployeeName LIKE 'S%' 

    THEN INSERT(EmployeeID, EmployeeName) VALUES(S.EmployeeID, S.EmployeeName)

WHEN MATCHED 

    THEN UPDATE SET T.EmployeeName = S.EmployeeName

WHEN NOT MATCHED BY SOURCE AND T.EmployeeName LIKE 'S%'

    THEN DELETE 

OUTPUT $action, inserted.*, deleted.*;

ROLLBACK TRAN;

GO 


 



OUTPUT 절의 결과는 다음과 같습니다.

$action   EmployeeID  EmployeeName EmployeeID  EmployeeName

--------- ----------- ------------ ----------- ------------

DELETE    NULL        NULL         101         Sara

DELETE    NULL        NULL         102         Stefano

INSERT    104         Steve        NULL        NULL

(3 row(s) affected)


ON 절에 추가 검색 조건을 지정하여(예: ON Source.EmployeeID = Target.EmployeeID AND EmployeeName LIKE 'S%' 지정) 프로세스의 초기에 입력 스트림의 행 수를 줄이면 쿼리 성능이 향상될 수 있습니다. 그러나 이 경우 예상치 못한 잘못된 결과가 나타날 수 있습니다. ON 절에 지정되는 추가 검색 조건은 원본 및 대상 데이터를 비교하는 데 사용되지 않으므로 잘못 적용될 수 있습니다.

다음 예에서는 잘못된 결과가 어떤 방식으로 발생할 수 있는지 보여 줍니다. 원본 및 대상 테이블을 비교하기 위한 검색 조건과 행을 필터링하기 위한 추가 검색 조건이 모두 ON 절에 지정됩니다. 추가 검색 조건에서는 원본과 대상의 일치를 확인할 필요가 없으므로 삽입 및 삭제 동작이 모든 입력 행에 적용됩니다. 실제로 필터링 조건 EmployeeName LIKE 'S%'는 무시됩니다. 문을 실행하면 inserted 및 deleted 테이블의 출력에서 두 개의 행이 잘못 수정되었음을 볼 수 있습니다. 대상 테이블에서 Mary가 잘못 삭제되고 Bob이 잘못 삽입되었습니다.




-- MERGE statement with join conditions that produce unexpected results.

USE tempdb;

GO

BEGIN TRAN;

MERGE Target AS T

USING Source AS S

ON (T.EmployeeID = S.EmployeeID AND T.EmployeeName LIKE 'S%' 

    AND S.EmployeeName LIKE 'S%' )

WHEN NOT MATCHED BY TARGET

    THEN INSERT(EmployeeID, EmployeeName) VALUES(S.EmployeeID, S.EmployeeName)

WHEN MATCHED 

    THEN UPDATE SET T.EmployeeName = S.EmployeeName

WHEN NOT MATCHED BY SOURCE

    THEN DELETE

OUTPUT $action, Inserted.*, Deleted.*;

ROLLBACK TRAN;

GO

 


OUTPUT 절의 결과는 다음과 같습니다.

$action   EmployeeID  EmployeeName EmployeeID  EmployeeName

--------- ----------- ------------ ----------- ------------

DELETE    NULL        NULL         100         Mary

DELETE    NULL        NULL         101         Sara

DELETE    NULL        NULL         102         Stefano

INSERT    103         Bob          NULL        NULL

INSERT    104         Steve        NULL        NULL

(5 row(s) affected)


검색 조건 지침


원본 및 대상 행을 비교하는 데 사용되는 검색 조건과 원본 또는 대상에서 행을 필터링하는 데 사용되는 추가 검색 조건을 정확하게 지정해야 올바른 결과를 얻을 수 있습니다. 다음 지침을 따르는 것이 좋습니다.

  • ON <merge_search_condition> 절에는 원본 및 대상 테이블의 데이터 비교를 위한 조건을 나타내는 검색 조건만 지정합니다. 즉, 대상 테이블에서 원본 테이블의 해당 열과 비교할 열만 지정해야 합니다.

  • 상수와 같은 다른 값에 대한 비교는 포함하지 않습니다.

원본 또는 대상 테이블에서 행을 필터링하려면 다음 방법 중 하나를 사용합니다.

  • 적절한 WHEN 절에 행 필터링을 위한 검색 조건을 지정합니다(예: WHEN NOT MATCHED AND S.EmployeeName LIKE 'S%' THEN INSERT...).

  • 필터링된 행을 반환하는 원본 또는 대상에 대한 뷰를 정의하고 이 뷰를 원본 또는 대상 테이블로 참조합니다. 대상 테이블에 대해 정의된 뷰의 모든 동작은 뷰 업데이트를 위한 조건을 충족해야 합니다. 뷰를 사용하여 데이터를 업데이트하는 방법은 뷰를 통해 데이터 수정을 참조하십시오.

  • WITH <common table expression> 절을 사용하여 원본 또는 대상 테이블에서 행을 필터링합니다. 이 방법은 ON 절에 추가 검색 조건을 지정하는 것과 비슷하며 잘못된 결과를 생성할 수 있으므로 사용하지 않는 것이 좋으며 사용할 경우 구현 전에 철저히 테스트해야 합니다.


1. 간단한 MERGE 문을 사용하여 INSERT 및 UPDATE 작업 수행

데이터 웨어하우스 데이터베이스에 각 고객이 특정 제품을 구매한 마지막 날짜를 추적하는 FactBuyingHabits 테이블이 있다고 가정해 보겠습니다. OLTP 데이터베이스에 있는 두 번째 테이블 Purchases는 특정 주간의 구매를 기록합니다. Purchases 테이블에서 특정 고객들이 한 번도 구매한 적이 없는 제품에 해당하는 행을 매주 FactBuyingHabits 테이블에 추가하려고 합니다. 이전에 이미 구매한 제품을 다시 구매하는 고객에 대한 행은 FactBuyingHabits 테이블에서 구매 날짜만 업데이트하려고 합니다. 이러한 삽입 및 업데이트 작업은 MERGE를 사용하여 단일 문으로 수행할 수 있습니다.

다음 예에서는 먼저 Purchases  FactBuyingHabits 테이블을 만들고 이 테이블에 일부 예제 데이터를 로드합니다. MERGE 문의 성능은 조인 키에서 UNIQUE 인덱스가 생성되면 향상되므로 클러스터형 인덱스는 두 테이블 모두에서 ProductID 열에 PRIMARY KEY 제약 조건을 생성하여 만들어집니다.

이 예에서 Purchases에는 2006년 8월 21일에 해당하는 주에 대한 구매가 포함됩니다. FactBuyingHabits에는 그 전 주에 대한 구매가 포함됩니다. 일반적으로 이 테이블은 훨씬 이전 날짜의 행으로 채워집니다.


USE AdventureWorks2008R2;
GO
IF OBJECT_ID (N'dbo.Purchases', N'U') IS NOT NULL 
    DROP TABLE dbo.Purchases;
GO

CREATE TABLE dbo.Purchases (
    ProductID int, CustomerID int, PurchaseDate datetime, 
    CONSTRAINT PK_PurchProdID PRIMARY KEY(ProductID,CustomerID));
GO

INSERT INTO dbo.Purchases VALUES(707, 11794, '20060821'),
(707, 15160, '20060825'),(708, 18529, '20060821'),
(711, 11794, '20060821'),(711, 19585, '20060822'),
(712, 14680, '20060825'),(712, 21524, '20060825'),
(712, 19072, '20060821'),(870, 15160, '20060823'),
(870, 11927, '20060824'),(870, 18749, '20060825');
GO

IF OBJECT_ID (N'dbo.FactBuyingHabits', N'U') IS NOT NULL 
    DROP TABLE dbo.FactBuyingHabits;
GO

CREATE TABLE dbo.FactBuyingHabits (
    ProductID int, CustomerID int, LastPurchaseDate datetime, 
    CONSTRAINT PK_FactProdID PRIMARY KEY(ProductID,CustomerID));
GO

INSERT INTO dbo.FactBuyingHabits VALUES(707, 11794, '20060814'),
(707, 18178, '20060818'),(864, 14114, '20060818'),
(866, 13350, '20060818'),(866, 20201, '20060815'),
(867, 20201, '20060814'),(869, 19893, '20060815'),
(870, 17151, '20060818'),(870, 15160, '20060817'),
(871, 21717, '20060817'),(871, 21163, '20060815'),
(871, 13350, '20060815'),(873, 23381, '20060815');
GO


이제 다음 데이터로 테이블이 채워집니다.

dbo.Purchases

ProductID   CustomerID  PurchaseDate

----------- ----------- -----------------------

707         11794       2006-08-20 00:00:00.000

707         15160       2006-08-25 00:00:00.000

708         18529       2006-08-21 00:00:00.000

711         11794       2006-08-20 00:00:00.000

711         19585       2006-08-22 00:00:00.000

712         14680       2006-08-26 00:00:00.000

712         21524       2006-08-26 00:00:00.000

712         19072       2006-08-20 00:00:00.000

870         15160       2006-08-23 00:00:00.000

870         11927       2006-08-24 00:00:00.000

870         18749       2006-08-25 00:00:00.000

dbo.FactBuyingHabits

ProductID   CustomerID  LastPurchaseDate

----------- ----------- -----------------------

707         11794       2006-08-14 00:00:00.000

707         18178       2006-08-18 00:00:00.000

864         14114       2006-08-18 00:00:00.000

866         13350       2006-08-18 00:00:00.000

866         20201       2006-08-15 00:00:00.000

867         20201       2006-08-14 00:00:00.000

869         19893       2006-08-15 00:00:00.000

870         17151       2006-08-18 00:00:00.000

870         15160       2006-08-17 00:00:00.000

871         21717       2006-08-17 00:00:00.000

871         21163       2006-08-15 00:00:00.000

871         13350       2006-08-15 00:00:00.000

873         23381       2006-08-15 00:00:00.000


두 테이블에는 공통적으로 Product-Customer 행이 있습니다. Customer 11794는 현재 주와 이전 주에 Product 707을 구매했으며 Customer 15160도 마찬가지로 현재 주와 이전 주에 Product 870을 구매했습니다. 이러한 행에서 WHEN MATCHED THEN 절을 사용하여 Purchases에 기록된 구매 날짜로 FactBuyingHabits를 업데이트합니다. WHEN NOT MATCHED THEN 절을 사용하여 다른 모든 행을 FactBuyingHabits에 삽입합니다.



MERGE dbo.FactBuyingHabits AS Target
USING (SELECT CustomerID, ProductID, PurchaseDate FROM dbo.Purchases) AS Source
ON (Target.ProductID = Source.ProductID AND Target.CustomerID = Source.CustomerID)
WHEN MATCHED THEN
    UPDATE SET Target.LastPurchaseDate = Source.PurchaseDate
WHEN NOT MATCHED BY TARGET THEN
    INSERT (CustomerID, ProductID, LastPurchaseDate)
    VALUES (Source.CustomerID, Source.ProductID, Source.PurchaseDate)
OUTPUT $action, Inserted.*, Deleted.*; 



2. UPDATE 및 DELETE 작업 수행

다음 예에서는 MERGE를 사용하여 SalesOrderDetail 테이블의 처리된 주문을 기반으로 AdventureWorks2008R2 예제 데이터베이스의 ProductInventory 테이블을 매일 업데이트합니다. 다음 MERGE 문을 사용하여 ProductInventory 테이블의 Quantity 열은 각 제품에 대해 각 날짜에 접수된 주문의 수를 빼는 방식으로 업데이트됩니다. 제품에 대한 주문의 수로 인해 제품의 재고가 0 이하로 떨어지면 해당 제품에 대한 행이 ProductInventory 테이블에서 삭제됩니다. 원본 테이블은 ProductID 열에서 집계됩니다. 이 집계가 수행되지 않는다면 원본 테이블에서 두 개 이상의 ProductID가 대상 테이블에 일치하고 MERGE 문이 오류를 반환하게 됩니다.


USE AdventureWorks2008R2; GO IF OBJECT_ID (N'Production.usp_UpdateInventory', N'P') IS NOT NULL     DROP PROCEDURE Production.usp_UpdateInventory;

GO CREATE PROCEDURE Production.usp_UpdateInventory @OrderDate datetime AS MERGE Production.ProductInventory AS target USING (SELECT ProductID, SUM(OrderQty) FROM Sales.SalesOrderDetail AS sod JOIN Sales.SalesOrderHeader AS soh ON sod.SalesOrderID = soh.SalesOrderID AND soh.OrderDate = @OrderDate GROUP BY ProductID) AS source (ProductID, OrderQty) ON (target.ProductID = source.ProductID) WHEN MATCHED AND target.Quantity - source.OrderQty <= 0 THEN DELETE WHEN MATCHED THEN UPDATE SET target.Quantity = target.Quantity - source.OrderQty, target.ModifiedDate = GETDATE() OUTPUT $action, Inserted.ProductID, Inserted.Quantity, Inserted.ModifiedDate, Deleted.ProductID, Deleted.Quantity, Deleted.ModifiedDate; GO EXECUTE Production.usp_UpdateInventory '20030501'


3. INSERT, UPDATE 및 DELETE 작업 수행

다음 예에서는 MERGE를 사용하여 원본 데이터와의 차이점에 따라 대상 테이블에서 행을 삽입, 업데이트 또는 삭제합니다. 각각 부서 관리자가 있는 5개 부서로 이루어진 소규모 기업을 가정해 보겠습니다. 이 회사는 부서 조직을 개편하기로 결정했습니다. 대상 테이블 dbo.Departments에서 조직 개편 결과를 구현하려면 MERGE 문에서 다음과 같은 변경 내용을 구현해야 합니다.

  • 기존 부서 일부는 변경되지 않습니다.

  • 기존 부서 일부에는 새로운 관리자가 임명됩니다.

  • 일부 부서는 새로 만들어집니다.

  • 일부 부서는 조직 개편 후 더 이상 존재하지 않게 됩니다.

다음 코드에서는 대상 테이블 dbo.Departments를 만들고 관리자 정보로 테이블을 채웁니다.


USE AdventureWorks2008R2;
GO
IF OBJECT_ID (N'dbo.Departments', N'U') IS NOT NULL 
    DROP TABLE dbo.Departments;
GO
CREATE TABLE dbo.Departments (DeptID tinyint NOT NULL PRIMARY KEY, DeptName nvarchar(30), 
    Manager nvarchar(50));
GO
INSERT INTO dbo.Departments 
    VALUES (1, 'Human Resources', 'Margheim'),(2, 'Sales', 'Byham'), 
           (3, 'Finance', 'Gill'),(4, 'Purchasing', 'Barber'),
           (5, 'Manufacturing', 'Brewer');


부서의 조직 변경 내용은 원본 테이블 dbo.Departments_delta에 저장됩니다. 다음 코드는 이 테이블을 만들고 채웁니다.


USE AdventureWorks2008R2;
GO
IF OBJECT_ID (N'dbo.Departments_delta', N'U') IS NOT NULL 
    DROP TABLE dbo.Departments_delta;
GO
CREATE TABLE dbo.Departments_delta (DeptID tinyint NOT NULL PRIMARY KEY, DeptName nvarchar(30), 
    Manager nvarchar(50));
GO
INSERT INTO dbo.Departments_delta VALUES 
    (1, 'Human Resources', 'Margheim'), (2, 'Sales', 'Erickson'),
    (3 , 'Accounting', 'Varkey'),(4, 'Purchasing', 'Barber'), 
    (6, 'Production', 'Jones'), (7, 'Customer Relations', 'Smith');
GO


마지막으로 다음 코드에서는 대상 테이블에 회사의 조직 개편을 반영하기 위해 MERGE 문을 사용하여 원본 테이블 dbo.Departments_delta와 대상 테이블 dbo.Departments를 비교합니다. 이 비교에 사용되는 검색 조건은 해당 문의 ON 절에서 정의됩니다. 비교 결과에 따라 다음과 같은 동작이 수행됩니다.

  • 두 테이블 모두에 있는 부서는 Departments 대상 테이블에서 새 이름, 새 관리자 또는 두 가지 모두를 사용하여 업데이트됩니다. 변경 사항이 없으면 아무것도 업데이트되지 않습니다. 이 작업은 WHEN MATCHED THEN 절에서 수행됩니다.

  • Departments에 없는 Departments_delta의 부서는 Departments에 삽입됩니다. 이 작업은 WHEN NOT MATCHED THEN 절에서 수행됩니다.

  • Departments에서 원본 테이블 Departments_delta에 없는 부서는 삭제됩니다. 이 작업은 WHEN NOT MATCHED BY SOURCE THEN 절에서 수행됩니다.


MERGE dbo.Departments AS d
USING dbo.Departments_delta AS dd
ON (d.DeptID = dd.DeptID)
WHEN MATCHED AND d.Manager <> dd.Manager OR d.DeptName <> dd.DeptName
    THEN UPDATE SET d.Manager = dd.Manager, d.DeptName = dd.DeptName
WHEN NOT MATCHED THEN
    INSERT (DeptID, DeptName, Manager)
        VALUES (dd.DeptID, dd.DeptName, dd.Manager)
WHEN NOT MATCHED BY SOURCE THEN
    DELETE
OUTPUT $action, 
       inserted.DeptID AS SourceDeptID, inserted.DeptName AS SourceDeptName, 
       inserted.Manager AS SourceManager, 
       deleted.DeptID AS TargetDeptID, deleted.DeptName AS TargetDeptName, 
       deleted.Manager AS TargetManager;    




Comments