Utilisation correcte des transactions dans SQL Server

236

J'ai 2 commandes et j'ai besoin que les deux soient exécutées correctement ou qu'aucune ne soit exécutée. Je pense donc que j'ai besoin d'une transaction, mais je ne sais pas comment l'utiliser correctement.

Quel est le problème avec le script suivant?

BEGIN TRANSACTION [Tran1]

INSERT INTO [Test].[dbo].[T1]
    ([Title], [AVG])
VALUES ('Tidd130', 130), ('Tidd230', 230)

UPDATE [Test].[dbo].[T1]
  SET [Title] = N'az2' ,[AVG] = 1
  WHERE [dbo].[T1].[Title] = N'az'

COMMIT TRANSACTION [Tran1]
GO

La INSERTcommande est exécutée, mais la UPDATEcommande a un problème.

Comment puis-je implémenter cela pour restaurer les deux commandes si l'une d'entre elles a une erreur d'exécution?

Saeid
la source

Réponses:

513

Ajoutez un bloc try / catch, si la transaction réussit, elle valide les modifications, si la transaction échoue, la transaction est annulée:

BEGIN TRANSACTION [Tran1]

  BEGIN TRY

      INSERT INTO [Test].[dbo].[T1] ([Title], [AVG])
      VALUES ('Tidd130', 130), ('Tidd230', 230)

      UPDATE [Test].[dbo].[T1]
      SET [Title] = N'az2' ,[AVG] = 1
      WHERE [dbo].[T1].[Title] = N'az'

      COMMIT TRANSACTION [Tran1]

  END TRY

  BEGIN CATCH

      ROLLBACK TRANSACTION [Tran1]

  END CATCH  
Darren
la source
1
Ne devrait pas BEGIN TRANSACTION [Tran1]être placé à l'intérieur TRY? Quoi qu'il en soit - morceau de code très simple et élégant.
Piotr Nawrot
4
@PiotrNawrot Non, si la création de la transaction a échoué, il n'est pas nécessaire de l'annuler dans la capture.
Monseigneur
114

Au début de la procédure stockée, il faut mettre SET XACT_ABORT ON pour demander au serveur SQL de restaurer automatiquement la transaction en cas d'erreur. Si omis ou réglé sur OFF, il faut tester @@ ERROR après chaque instruction ou utiliser le bloc de restauration TRY ... CATCH .

Nikola Markovinović
la source
2
En d'autres termes, votre transaction n'est pas atomique sauf si vous définissez d'abord XACT_ABORT ON.
4h du
Il est difficile de voir avec un soulignement d'URL, mais il y a un trait de soulignement dansXACT_ABORT
BurnsBA
32

Approche facile:

CREATE TABLE T
(
    C [nvarchar](100) NOT NULL UNIQUE,
);

SET XACT_ABORT ON -- Turns on rollback if T-SQL statement raises a run-time error.
SELECT * FROM T; -- Check before.
BEGIN TRAN
    INSERT INTO T VALUES ('A');
    INSERT INTO T VALUES ('B');
    INSERT INTO T VALUES ('B');
    INSERT INTO T VALUES ('C');
COMMIT TRAN
SELECT * FROM T; -- Check after.
DELETE T;
Bohdan
la source