1. 程式人生 > >SQLSERVER merge的簡單用法

SQLSERVER merge的簡單用法

 MERGE INTO TEST_IN_COPY3 a USING (
SELECT
'武漢-北京998' AS NAME,
'2017 - 11 - 21 11 : 53 : 49.0000000 + 00 : 00' AS datetimeoffseta,
'2017-11-10 11:52:20' AS datetim2e,
998 AS ID,
'2017-11-07 11:52:10' AS datetimea,
'2017-11-10 00:00:00' AS datea,
5.5600 AS numerica,
5.55 AS floata
) b ON (a.ID = b.ID)
WHEN MATCHED THEN
UPDATE
SET a.NAME = b.NAME,
 a.datetimeoffseta = b.datetimeoffseta,
 a.datetim2e = b.datetim2e,
 a.datetimea = b.datetimea,
 a.datea = b.datea,
 a.numerica = b.numerica,
 a.floata = b.floata
WHEN NOT MATCHED THEN
INSERT (
NAME,
datetimeoffseta,
datetim2e,
ID,
datetimea,
datea,
numerica,
floata
)
VALUES
(
b.NAME,
b.datetimeoffseta,
b.datetim2e,
b.ID,
b.datetimea,
b.datea,
b.numerica,
b.floata

) ;

下面是主要的同步操作

MERGE INTO - 資料的目的地,將資料最終 MERGE 到的表物件

USING 與源表連線 ON 關聯的條件

WHEN MATCHED - 如果匹配成功,即關聯條件成功 (這時就應該將 SOURCE 中其它的所有欄位值更新到 TARGET 表中)

WHEN NOTMATCHED BY TARGET - 如果匹配不成功 (TARGET 中沒有這一條記錄但是 SOURCE 表有,說明 SOURCE 表多了新資料因此應該插入到 TARGET 表中)

WHEN NOTMATCHED BY SOURCE - 如果匹配不成功 (SOURCE 中沒有這一條記錄但是 TARGET 表有,說明 SOURCE 表可能把這條資料刪除了,所以 TARGET 也應該刪除)

MERGE INTO @TargetTable AS T           
USING @SourceTable AS S                
   ON T.ID = S.ID                      
WHEN MATCHED         
   THEN UPDATE SET T.DSPT = S.DSPT  
WHEN NOT MATCHED BY TARGET   
   THEN INSERT VALUES(S.ID,S.DSPT)
WHEN NOT MATCHED BY SOURCE            
   THEN DELETE
OUTPUT $ACTION AS
[ACTION], Deleted.ID AS 'Deleted ID', Deleted.DSPT AS 'Deleted Description', Inserted.ID AS 'Inserted ID', Inserted.DSPT AS 'Inserted Description' INTO @Log;

還要注意的是有一些限制條件:

  • 在 Merge Matched 操作中,只能允許執行 UPDATE 或者 DELETE 語句。
  • 在 Merge Not Matched 操作中,只允許執行 INSERT 語句。
  • 一個 Merge 語句中出現的 Matched 操作,只能出現一次 UPDATE 或者 DELETE 語句,否則就會出現下面的錯誤 - An action of type 'WHEN MATCHED' cannot appear more than once in a 'UPDATE' clause of a MERGE statement.
  • Merge 語句最後必須包含分號,以 ; 結束。

執行一下上面的 MERGE 語句檢視一下結果,兩個表的資料一模一樣了 -

ID = 1,2,3 的記錄在 Source 表和Target 表都存在,因此執行的是 UPDATE 操作。

ID = 4,5 的記錄在 Source 表存在,但是在 Target 表不存在,因此執行的是 INSERT 操作。

ID = 6,7 的記錄在 Target 表存在,但是在 Source 表不存在,因此執行的是 DELETE 操作。

22222222222222

使用merge同時執行insert和update操作

我們經常會有這樣的需求,根據某個欄位或多個欄位查詢表中的一行或多行資料,如果查詢成功得到匹配項,更新其中的其他一個或多個欄位;如果查詢失敗則將“某個欄位或多個欄位”作為新的一行中的資料插入到表中。第一種方法是先更新,然後根據@@rowcount判斷是否有匹配項,如果沒有則插入。先使用下面的 程式碼建立一個儲存過程。

複製程式碼 1 use AdventureWorks
2 go 3 createprocedure dbo.InsertUnitMeasure @UnitMeasureCodenchar(3),@Namenvarchar(25)
4 as 5 begin 6 set nocount on;
7 update Production.UnitMeasure set Name=@Namewhere UnitMeasureCode=@UnitMeasureCode 8 if(@@ROWCOUNT=0)
9 begin10 insertinto Production.UnitMeasure(Name,UnitMeasureCode)values(@Name,@UnitMeasureCode)
11 end12 end13 go 複製程式碼

記得見過這樣的筆試題目,要求是插入不存在的行,只要把上面語句中的update改成select就可以了,當時沒有寫出來,現在恍然大悟,也許是在考察@@ROWCOUNT的用法吧。這個語句也可以使用merge語句實現。下面我們使用merge關鍵字來修改這個儲存過程。

複製程式碼 1 alterprocedure dbo.InsertUnitMeasure @UnitMeasureCodenchar(3),@Namenvarchar(25)
2 as 3 begin 4 set nocount on 5 merge Production.UnitMeasure as target
6 using (select@UnitMeasureCode,@Name) as source (UnitMeasureCode,Name)
7 on (target.UnitMeasureCode=source.UnitMeasureCode)
8 when matched thenupdateset Name=source.Name
9 whennot matched theninsert(UnitMeasureCode,Name)values(source.UnitMeasureCode,Name)
10 output deleted.*,$action,inserted.*into MyTempTable;
11 end12 go 複製程式碼

這個語句使用merge修改儲存過程,這個語句中又出現我不太瞭解的關鍵字using和$action。Using是用來指定和表InsertUnitMeasure中相匹配的資料來源,這裡的資料來源來自外部輸入,是通過兩個輸入引數得到。$action可能是一個佔位符,表示上面的when字句進行的操作