What is the MERGE statement, and what are its pitfalls?
Quick Answer
MERGE does an upsert in one statement: WHEN MATCHED THEN UPDATE, WHEN NOT MATCHED THEN INSERT, optionally WHEN NOT MATCHED BY SOURCE THEN DELETE. It's concise but has a long history of bugs and concurrency hazards — many teams prefer an explicit UPDATE then INSERT (or the reverse) with proper locking.
MERGE combines insert, update and delete against a target based on whether a source row matches — the classic upsert. It reads nicely, but it has a reputation: there have been real correctness bugs, and by default it's not safe under concurrency — two sessions can both decide to insert and one gets a key violation. If you must use it for a single-row upsert you need HOLDLOCK on the target. Honestly, for OLTP upserts I usually write an explicit update, check @@ROWCOUNT, and insert if it was zero, all in a transaction. MERGE is genuinely good for batch ETL loads from a staging table.
- Under concurrency
MERGEcan still hit primary-key violations or deadlocks unless you useHOLDLOCK/SERIALIZABLEon the target. - Microsoft has documented multiple
MERGEcorrectness bugs over the years. - A safe single-row upsert:
UPDATE ... IF @@ROWCOUNT = 0 INSERT ...inside a transaction, or rely on a unique index +INSERT ... WHERE NOT EXISTS. MERGEshines for set-based ETL/staging loads where concurrency isn't a factor.