SQLSERVER merge的簡單用法
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 AdventureWorks2 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字句進行的操作