Say I have a table with an identity field. I want to insert a record in it if it doesn't already exist. In the below example, I check if the value stored in @Field1 already exists in the table. If not, I insert a new record:
Definition of the table:
MyTable (MyTableId int Identity not null, Field1 int not null, Field2 int not null)
This is how I check if the value already exists and insert it if necessary
merge MyTable as t using (@Field1, @Field2) as s (Field1,Field2) on (t.Field1=s.Field1) when not matched then insert (Field1,Field2) values (s.Field1,s.Field2);
Getting the identity value when the record didn't already exist in the table can be done by adding:
output Inserted.MyTableId
but what if the record was already in the table (ie if there was a match)?
The only way I found is to query the table after executing the Merge statement:
select MyTableId from MyTable where Field1=@Field1
Is there a way to get the identity value directly from the Merge?
Once we insert a row in a table, the @@IDENTITY function column gives the IDENTITY value generated by the statement. If we run any query that did not generate IDENTITY values, we get NULL value in the output. The SQL @@IDENTITY runs under the scope of the current session.
WHEN MATCHED clause in SQL Server MERGE statement is used to update, delete the rows in the target table when the rows are matched with the source table based on the join condition. In this case, Locations is the target table, Locations_stage is the source table and the column LocationID is used in the join condition.
The MERGE statement can have, at most, two WHEN MATCHED clauses. If two clauses are specified, the first clause must be accompanied by an AND <search_condition> clause. For any given row, the second WHEN MATCHED clause is only applied if the first isn't.
A WHEN NOT MATCHED clause is executed if no target-table row joined while forming the candidate row. WHEN MATCHED and WHEN NOT MATCHED clauses can be specified in any order, but the first clause applicable to a candidate row is the one executed by that row.
In the case when the record already exists, you can store the matched id into a variable like this:
DECLARE @MatchedId INTEGER; MERGE MyTable as t .... .... WHEN MATCHED THEN UPDATE SET @MatchedId = t.MyTableId;
UPDATE:
Here's a full example. This demonstrates one way:
DECLARE @UpdateVariable bit DECLARE @ChangeResult TABLE (ChangeType VARCHAR(10), Id INTEGER) DECLARE @Data TABLE (Id integer IDENTITY(1,1), Val VARCHAR(10)) INSERT @Data ([Val]) VALUES ('A'); MERGE @data AS TARGET USING (SELECT 'A' AS Val UNION ALL SELECT 'B' AS Val) AS SOURCE ON TARGET.Val = SOURCE.Val WHEN NOT MATCHED THEN INSERT ([Val]) VALUES (SOURCE.Val) WHEN MATCHED THEN UPDATE SET @UpdateVariable = 1 OUTPUT $action, inserted.Id INTO @ChangeResult; SELECT * FROM @data SELECT * FROM @ChangeResult
Points to note are:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With