Click here to monitor SSC
SQLServerCentral is supported by Red Gate Software Ltd.
 
Log in  ::  Register  ::  Not logged in
 
 
 
        
Home       Members    Calendar    Who's On


Add to briefcase 12»»

MERGE vs IF EXISTS with INSERT UPDATE Expand / Collapse
Author
Message
Posted Wednesday, September 19, 2012 9:40 AM


SSC-Addicted

SSC-AddictedSSC-AddictedSSC-AddictedSSC-AddictedSSC-AddictedSSC-AddictedSSC-AddictedSSC-Addicted

Group: General Forum Members
Last Login: Wednesday, May 15, 2013 5:02 AM
Points: 403, Visits: 904
Hi,

SQL Server has the MERGE statement and some people advise to use it instead of IF EXISTS with INSERT / UPDATE...
Is it worth upgrading from IF EXISTS .. to MERGE?
CREATE PROCEDURE usp_Upsert_teste1_1 
@ID INT,
@Desc VARCHAR(100)
AS
IF EXISTS (SELECT TOP 1 1 FROM teste1 WHERE ID = @ID)
UPDATE teste1 SET Description = @Desc WHERE ID = @ID
ELSE
INSERT INTO teste1 (ID, Description) VALUES (@ID, @Desc)
GO

CREATE PROCEDURE usp_Upsert_teste1_2
@ID INT,
@Desc VARCHAR(100)
AS
MERGE teste1 AS target
USING (SELECT @ID, @Desc) AS source (ID, Dsc)
ON target.ID = source.ID
WHEN MATCHED THEN
UPDATE SET target.Description = source.Dsc
WHEN NOT MATCHED THEN
INSERT (ID, Description) VALUES (source.ID, source.Dsc);

The execution plan is slower on the 1st sp because of the IF... The INSERT or UPDATE are as fast (according to execution plan) as the MERGE.

Thanks,
Pedro




If you need to work better, try working less...
Post #1361447
Posted Wednesday, September 19, 2012 9:53 AM


SSCoach

SSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoach

Group: General Forum Members
Last Login: Tuesday, May 21, 2013 1:55 PM
Points: 15,442, Visits: 9,571
If you need to maintain backwards compatibility with versions of SQL Server prior to 2008, then don't use Merge. Otherwise, it does have advantages.

The main advantage, from my perspective, is that you can do the action in one statement. That means less code to maintain, and it's obvious that it's an upsert instead of possibly two different actions. And, since a Merge statement can use either an Output Into or be wrapped in an Insert Select with a simpler Output clause, you can do your logging in one place instead of two (if you need to do audit logging, that is).

It also has advantages over Update From, if you use that, because it will throw an error instead of doing the wrong thing, if two rows could end up updating the same row in the destination.

If 99% of the time, an Update will happen, then you're better off with:

Update
if @@rowcount = 0
Insert

More efficient that way.

Beyond those points, it's really up to you. I like Merge, but it took a while to get used to the syntax.


- Gus "GSquared", RSVP, OODA, MAP, NMVP, FAQ, SAT, SQL, DNA, RNA, UOI, IOU, AM, PM, AD, BC, BCE, USA, UN, CF, ROFL, LOL, ETC
Property of The Thread

"Nobody knows the age of the human race, but everyone agrees it's old enough to know better." - Anon
Post #1361463
Posted Wednesday, September 19, 2012 10:17 AM
SSCrazy

SSCrazySSCrazySSCrazySSCrazySSCrazySSCrazySSCrazySSCrazy

Group: General Forum Members
Last Login: Yesterday @ 10:39 AM
Points: 2,556, Visits: 4,398
And another thing to mention for MERGE is that SQL Server kind of splits the data into up to three "streams" and executes INSERT, UPDATE and DELETE (if required).
So, for example, if you have a single trigger for INSERT, UPDATE, DELETE it will still be executed separately three times. You have no control over what will happen first, as order of execution is not guaranteed...
Another small caveat for using INSTEAD OF triggers, in case if you want use MERGE, they should not be present at all or they should be implemented for all three operations.


_____________________________________________
"The only true wisdom is in knowing you know nothing"
"O skol'ko nam otkrytiy chudnyh prevnosit microsofta duh!"
(So many miracle inventions provided by MS to us...)

How to post your question to get the best and quick help
Post #1361483
Posted Wednesday, September 19, 2012 10:27 AM


SSCarpal Tunnel

SSCarpal TunnelSSCarpal TunnelSSCarpal TunnelSSCarpal TunnelSSCarpal TunnelSSCarpal TunnelSSCarpal TunnelSSCarpal TunnelSSCarpal Tunnel

Group: General Forum Members
Last Login: Yesterday @ 9:39 AM
Points: 4,247, Visits: 9,500
One thing which I have noticed with MERGE is that it does not natively provide separate Updated/Inserted/Deleted counts.

You need to code an OUTPUT clause and use $Action to get these. Without that you just get a total 'rows affected' count in @@RowCount.


____________________________________________________________________________________________

Help us to help you. For better, quicker and more focused answers to your questions, consider following the advice in this link:

http://www.sqlservercentral.com/articles/Best+Practices/61537/

If you are asking for help and your post does not contain a question, you should expect responses which do not contain any answers. Put a question mark in there somewhere - it's not rocket science.
Post #1361491
Posted Wednesday, September 19, 2012 11:25 AM


SSCoach

SSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoach

Group: General Forum Members
Last Login: Tuesday, May 21, 2013 1:55 PM
Points: 15,442, Visits: 9,571
Phil Parkin (9/19/2012)
One thing which I have noticed with MERGE is that it does not natively provide separate Updated/Inserted/Deleted counts.

You need to code an OUTPUT clause and use $Action to get these. Without that you just get a total 'rows affected' count in @@RowCount.


Yep. And that can be a good thing if you want the count for an atomic upsert, or a bad thing if you need to know which had which counts. Still, can be done within the statement, instead of 3 counts (one for each action). And, if you use Pivot on the Output, you can even get all three counts in a single row, which is kind of cool.


- Gus "GSquared", RSVP, OODA, MAP, NMVP, FAQ, SAT, SQL, DNA, RNA, UOI, IOU, AM, PM, AD, BC, BCE, USA, UN, CF, ROFL, LOL, ETC
Property of The Thread

"Nobody knows the age of the human race, but everyone agrees it's old enough to know better." - Anon
Post #1361531
Posted Thursday, September 20, 2012 12:41 AM


SSCrazy

SSCrazySSCrazySSCrazySSCrazySSCrazySSCrazySSCrazySSCrazy

Group: General Forum Members
Last Login: Yesterday @ 7:24 PM
Points: 2,346, Visits: 3,192
GSquared (9/19/2012)
Phil Parkin (9/19/2012)
One thing which I have noticed with MERGE is that it does not natively provide separate Updated/Inserted/Deleted counts.

You need to code an OUTPUT clause and use $Action to get these. Without that you just get a total 'rows affected' count in @@RowCount.


Yep. And that can be a good thing if you want the count for an atomic upsert, or a bad thing if you need to know which had which counts. Still, can be done within the statement, instead of 3 counts (one for each action). And, if you use Pivot on the Output, you can even get all three counts in a single row, which is kind of cool.


Unless I'm mistaken, it would be even cooler if you could assign the 3 PIVOTed columns directly to local variables instead of being forced to INSERT them into a 3 column table in the outer wrapper of the composable DML.



No loops! No CURSORs! No RBAR! Hoo-uh!

INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?

Need to UNPIVOT? Why not CROSS APPLY VALUES instead?
Since random numbers are too important to be left to chance, let's generate some!
Are you too recursively challenged?
Splitting strings based on patterns can be fast!
Post #1361754
Posted Thursday, September 20, 2012 6:07 AM


SSCoach

SSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoach

Group: General Forum Members
Last Login: Tuesday, May 21, 2013 1:55 PM
Points: 15,442, Visits: 9,571
dwain.c (9/20/2012)
GSquared (9/19/2012)
Phil Parkin (9/19/2012)
One thing which I have noticed with MERGE is that it does not natively provide separate Updated/Inserted/Deleted counts.

You need to code an OUTPUT clause and use $Action to get these. Without that you just get a total 'rows affected' count in @@RowCount.


Yep. And that can be a good thing if you want the count for an atomic upsert, or a bad thing if you need to know which had which counts. Still, can be done within the statement, instead of 3 counts (one for each action). And, if you use Pivot on the Output, you can even get all three counts in a single row, which is kind of cool.


Unless I'm mistaken, it would be even cooler if you could assign the 3 PIVOTed columns directly to local variables instead of being forced to INSERT them into a 3 column table in the outer wrapper of the composable DML.


Yeah, would be very cool if Output worked more like Select, and could assign values to variables using inline sub-queries and things like that. Maybe a future version will.


- Gus "GSquared", RSVP, OODA, MAP, NMVP, FAQ, SAT, SQL, DNA, RNA, UOI, IOU, AM, PM, AD, BC, BCE, USA, UN, CF, ROFL, LOL, ETC
Property of The Thread

"Nobody knows the age of the human race, but everyone agrees it's old enough to know better." - Anon
Post #1361899
Posted Friday, September 21, 2012 8:34 AM


Hall of Fame

Hall of FameHall of FameHall of FameHall of FameHall of FameHall of FameHall of FameHall of FameHall of Fame

Group: General Forum Members
Last Login: Today @ 2:30 PM
Points: 3,582, Visits: 5,131
For concurrency reasons it is MUCH preferred to use MERGE I think. I have seen a number of clients over the years get bad data in their system doing multiple steps for what you are trying to do.

Do be careful if you have triggers on your tables though, or if you need to test @@ROWCOUNT. Some unexpected things can arise.


Best,

Kevin G. Boles
SQL Server Consultant
SQL MVP 2007-2012
TheSQLGuru at GMail
Post #1362716
Posted Friday, September 21, 2012 11:46 AM


SSCoach

SSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoachSSCoach

Group: General Forum Members
Last Login: Tuesday, May 21, 2013 1:55 PM
Points: 15,442, Visits: 9,571
TheSQLGuru (9/21/2012)
For concurrency reasons it is MUCH preferred to use MERGE I think. I have seen a number of clients over the years get bad data in their system doing multiple steps for what you are trying to do.

Do be careful if you have triggers on your tables though, or if you need to test @@ROWCOUNT. Some unexpected things can arise.


Yeah, if you do the multi-step version, transaction control is critical. That's for sure!


- Gus "GSquared", RSVP, OODA, MAP, NMVP, FAQ, SAT, SQL, DNA, RNA, UOI, IOU, AM, PM, AD, BC, BCE, USA, UN, CF, ROFL, LOL, ETC
Property of The Thread

"Nobody knows the age of the human race, but everyone agrees it's old enough to know better." - Anon
Post #1362874
Posted Saturday, September 22, 2012 12:14 PM


SSCommitted

SSCommittedSSCommittedSSCommittedSSCommittedSSCommittedSSCommittedSSCommittedSSCommitted

Group: General Forum Members
Last Login: Tuesday, January 15, 2013 11:11 AM
Points: 1,945, Visits: 2,782
MERGE gets rid of procedural code and it is ANSI/ISO Standard. Use it. In the future, MS will steal optimizations that IBM and Oracle have had for years and incorporate them. MERGE can only get better.

Books in Celko Series for Morgan-Kaufmann Publishing
Analytics and OLAP in SQL
Data and Databases: Concepts in Practice
Data, Measurements and Standards in SQL
SQL for Smarties
SQL Programming Style
SQL Puzzles and Answers
Thinking in Sets
Trees and Hierarchies in SQL
Post #1363149
« Prev Topic | Next Topic »

Add to briefcase 12»»

Permissions Expand / Collapse