0

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) */ ; 

1 Answer 1

1

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).

Sign up to request clarification or add additional context in comments.

1 Comment

This is the first I have seen a filtered index. That is awesome. I can use that in many places.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.