Sql-Server
如何在 SQL Server 的多鍵 MERGE 中僅刪除相關記錄?
假設你有這樣的東西:
源表(變數):
Values ( LeftId INT NOT NULL, RightId INT NOT NULL, CustomValue varchar(100) NULL )
目標表:
Mapping ( LeftId INT NOT NULL, RightId INT NOT NULL, CustomValue varchar(100) NULL )
我想合併
Values
到Target
以下規則:
- 匹配上
source.LeftId = target.LeftId AND source.RightId = target.RightId
- 在目標中匹配時,更新
CustomValue
- 當目標中不匹配時,插入
- 刪除目標中與源中的a 匹配的任何不匹配值*,*
LeftId
即僅刪除與LefId
我正在合併的 s 相關的記錄。(最後一條規則很難描述,抱歉!)
例如:
資源:
1, 10, foo 1, 11, foo
目標:
1, 10, bar 1, 12, foo 2, 20, car
合併結果:
結果目標:
1, 10, foo (updated) 1, 11, foo (inserted) 1, 12, foo (deleted) 2, 20, car (unchanged)
所以…
這是我到目前為止所擁有的,它負責
update
andinsert
:MERGE Mapping AS target USING (SELECT LeftId, RightId, CustomValue FROM @Values) AS source (LeftId, RightId, CustomValue) ON target.LeftId = source.LeftId AND target.RightId = source.RightId WHEN NOT MATCHED THEN INSERT (LeftId, RightId, CustomValue) VALUES (source.LeftId, source.RightId, source.CustomValue) WHEN MATCHED THEN UPDATE SET CustomValue = source.CustomValue;
我該如何做
delete
我的規則的一部分?
這是
DELETE
我想到的單獨操作:DELETE m FROM dbo.Mapping AS m WHERE EXISTS (SELECT 1 FROM @Values WHERE LeftID = m.LeftID) AND NOT EXISTS (SELECT 1 FROM @Values WHERE LeftID = m.LeftID AND RightID = m.RightID);
正如我在這裡概述的那樣,對於左反半連接,該
NOT EXISTS
模式通常會優於該LEFT JOIN / NULL
模式(但您應該始終進行測試)。不確定您的總體目標是清晰度還是性能,因此只有您可以判斷這是否比
NOT MATCHED BY source
選項更符合您的要求。您必須定性地查看計劃,定量地查看計劃和/或執行時指標,才能確定。如果您希望您的
MERGE
命令保護您免受多個獨立語句可能發生的競爭條件的影響,您最好通過將其更改為:MERGE dbo.Mapping WITH (HOLDLOCK) AS target
(來自Dan Guzman 的博文。)
就個人而言,我會在沒有 的情況下完成所有這些
MERGE
,因為存在未解決的錯誤以及其他原因。並且Paul White 似乎也推薦單獨的 DML 語句。這就是我添加模式前綴的原因:在創建、影響等時,您應該始終按模式引用對象。