Pour les futurs étudiants du cours "MS SQL Server Developer" a préparé une traduction de l'article.
Nous vous invitons également à regarder le webinaire ouvert sur "Graph Databases in SQL Server" . Dans cette leçon, les participants, avec un expert, examineront ce que sont les bases de données de graphiques et quelles sont les options pour travailler avec des graphiques et des hiérarchies dans SQL Server.

Je pense que tout le monde connaît déjà mon opinion sur MERGE et pourquoi je m'en éloigne. Mais voici un autre anti-pattern que je rencontre constamment lorsqu'il est nécessaire d'exécuter UPSERT (UPdate inSERT - update a row if it exists, and insert if it does not exist):
IF EXISTS (SELECT 1 FROM dbo.t WHERE [key] = @key)
BEGIN
UPDATE dbo.t SET val = @val WHERE [key] = @key;
END
ELSE
BEGIN
INSERT dbo.t([key], val) VALUES(@key, @val);
END
Cela a l'air assez logique et correspond à la façon dont nous y pensons:
Y a-t-il une chaîne pour la clé donnée?
OUI : Nous mettons à jour cette ligne.
: .
, , , — . , (, , ). -, , :

, , , ( ):
UPDATE , ( "", "" " "). , . (Paul White) , (Martin Smith) .
, INSERT :
(deadlock) - ;
(key violation), ;
, .
— , . , XACT_ABORT , — , . , IF EXISTS ( ), . , , .
« ...»
(Dan Guzman) Conditional INSERT/UPDATE Race Condition, "UPSERT" Race Condition With MERGE.
(Michael Swart) Mythbusting: Concurrent Update/Insert Solutions, , , . MERGE Be Careful with the Merge Statement. .
, ( , ):
BEGIN TRANSACTION;
UPDATE dbo.t WITH (UPDLOCK, SERIALIZABLE) SET val = @val WHERE [key] = @key;
IF @@ROWCOUNT = 0
BEGIN
INSERT dbo.t([key], val) VALUES(@key, @val);
END
COMMIT TRANSACTION;
? UPDLOCK ?
UPDLOCK ( , ).
SERIALIZABLE ( , ).
, 1000% . ( ) . , , , . , :

:
, , .
, «» . ( ), UPDATE.
, , - , «» .
, . , . , , .
, UPDATE ?
, UPDATE . , , INSERT, INSERT , UPDATE, UPSERT:
BEGIN TRANSACTION;
INSERT dbo.t([key], val)
SELECT @key, @val
WHERE NOT EXISTS
(
SELECT 1 FROM dbo.t WITH (UPDLOCK, SERIALIZABLE)
WHERE [key] = @key
);
IF @@ROWCOUNT = 0
BEGIN
UPDATE dbo.t SET val = @val WHERE [key] = @key;
END
COMMIT TRANSACTION;
« », INSERT :
BEGIN TRANSACTION;
BEGIN TRY
INSERT dbo.t([key], val) VALUES(@key, @val);
END TRY
BEGIN CATCH
UPDATE dbo.t SET val = @val WHERE [key] = @key;
END CATCH
COMMIT TRANSACTION;
. / . .
?
INSERT / UPDATE, (Justin Pealing) , , , ?
- (TVP, Table-Valued Parameters), UPDATE JOIN, INSERT, NOT EXISTS. , :
CREATE PROCEDURE dbo.UpsertTheThings
@tvp dbo.TableType READONLY
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION;
UPDATE t WITH (UPDLOCK, SERIALIZABLE)
SET val = tvp.val
FROM dbo.t AS t
INNER JOIN @tvp AS tvp
ON t.[key] = tvp.[key];
INSERT dbo.t([key], val)
SELECT [key], val FROM @tvp AS tvp
WHERE NOT EXISTS (SELECT 1 FROM dbo.t WHERE [key] = tvp.[key]);
COMMIT TRANSACTION;
END
- , TVP (XML, - ..), JOIN . INSERT — UPDATE .
UPSERT- , , , , . , IF EXIST. (Paul White, sql.kiwi | @SQK_Kiwi) — .
MERGE (, - MERGE-), .
"MS SQL Server Developer".
« SQL Server».