Reputation: 10063
I am downloading data that will have duplicates with previously downloaded data.
I am successfully using a MERGE statement to throw away the duplicates based on transaction number. Supposedly that is sufficient, but I would like to monitor if the detail ever changes on a particular transaction.
To that end I added a when matched
clause on the merge
with an additional insert that identifies the record as a duplicate.
This logic should not trigger very often so I am not too concerned that this method (if it worked) would report the same duplicate multiple times.
When I prepare this code I get this error message:
An action of type 'INSERT' is not allowed in the 'WHEN MATCHED' clause of a MERGE statement.
Is there a way to get the duplicate record to insert into this table or another table using the MERGE statement?
I am open to other solutions, but I would really like to find a way to do this with the MERGE statement because it would impact my code the least.
MERGE INTO dbo.TransactionDetail as t
USING (SELECT @TransNr --bigint
,@Detail -- [VARCHAR](50) NOT NULL
) as s
([TranNr]
,[Detail]
)
on t.TranNr = s.TranNr and t.CHANGED_RECORD = 0
when not matched then
INSERT (CHANGED_RECORD
,[TranNr]
,[Detail]
)
VALUES(0, s.TranNr, s.Detail)
/* Adding this does not allow statement to be prepared....
when matched and s.Detail <> t.Detail
then
INSERT (CHANGED_RECORD
,[TranNr]
,[Detail]
)
VALUES(1, s.TranNr, s.Detail)
*/
;
Upvotes: 0
Views: 2928
Reputation: 5684
You can use an INSERT
statement, like this:
INSERT INTO dbo.TransactionDetail (CHANGED_RECORD,TranNr,Detail)
SELECT CASE WHEN EXISTS (
SELECT * FROM dbo.TransactionDetail
WHERE TranNr=@TransNr AND CHANGED_RECORD=0 AND Detail<>@Detail
) THEN 1 ELSE 0 END AS CHANGED_RECORD,
@TransNr AS TranNr, @Detail AS Detail
WHERE NOT EXISTS (
SELECT * FROM dbo.TransactionDetail
WHERE TranNr=@TransNr AND CHANGED_RECORD=0 AND Detail=@Detail
)
This will skip inserting if a row which has CHANGED_RECORD=0
has the same detail. However, if the same detail it's found in another row which has CHANGED_RECORD=1
, a new duplicate would be inserted. To avoid that, remove the AND CHANGED_RECORD=0
condition from the WHERE NOT EXISTS
subquery.
You may also want to create a unique filtered index, to ensure unicity for the rows which have CHANGED_RECORD=0
:
CREATE UNIQUE INDEX IX_TransactionDetail_Filtered
ON TransactionDetail (TranNr) /*INCLUDE (Detail)*/ WHERE CHANGED_RECORD=0
The INCLUDE (Detail)
clause could also marginally improve performance of queries that are looking for the Detail
of the rows which have CHANGED_RECORD=0
(at the expense of some additional disk space and a small performance penalty when updating the Detail
column of existing rows).
Upvotes: 1