MERGE Query and deleting records
merge, sql-server, sql-server-2008-r2, t-sql
Solution
I can think of two obvious ways but both of them involve processing the TVP again.
The first is simply to change the `DELETE` condition
WHEN NOT MATCHED BY SOURCE
AND target.AccountId IN(SELECT AccountId FROM @Items) THEN
DELETE;
The second is to use a CTE to restrict the target
WITH cte as
(
SELECT ItemId, AccountId
FROM @myTable m
WHERE EXISTS
(SELECT * FROM @Items i WHERE i.AccountId = m.AccountId)
)
MERGE INTO cte as target
USING @Items Items
ON (Items.AccountId = target.AccountId) AND
(Items.ItemId = target.ItemId)
WHEN NOT MATCHED BY TARGET THEN
INSERT (AccountId, ItemId)
VALUES (Items.AccountId, Items.ItemId)
WHEN NOT MATCHED BY SOURCE THEN
DELETE;
Problem
I have a table that looks something like: ``` AccountID, ItemID 1, 100 1, 200 2, 300 ``` I have a proc that accepts a table value parameter which updates the Items associated with an account. We'll pass something like the following: ``` AccountID, ItemID 3, 100 3, 200 ``` The proc looks something like: ``` procedure dbo.MyProc( @Items as dbo.ItemListTVP READONLY ) AS BEGIN MERGE INTO myTable as target USING @Items on (Items.AccountId = target.AccountId) AND (Items.ItemId = target.ItemId) WHEN NOT MATCHED BY TARGET THEN INSERT (AccountId, ItemId) VALUES (Items.AccountId, Items.ItemId) ; END ``` Based on the passed in data I expect it to add 2 new records to the table, which it does. What I want is to have a WHEN NOT MATCHED BY SOURCE clause which will remove items for the specified account that aren't matched. For example, if I pass ``` AccountID, ItemID 1, 100 1, 400 ``` Then I want it to delete the record having 1, 200; but leave ALL of the others. If I just do: ``` WHEN NOT MATCHED BY SOURCE THEN DELETE; ``` then it will remove all records for accounts not referenced (ie: account ids 2 and 3). How can I do this? Thanks,