web-dev-qa-db-fra.com

SQL Server - les transactions annulent-elles les erreurs?

Nous avons une application cliente qui exécute du code SQL sur un serveur SQL 2005, telle que:

BEGIN TRAN;
INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
COMMIT TRAN;

Il est envoyé par une longue commande de chaîne.

Si l'une des insertions échoue ou si une partie de la commande échoue, SQL Server annule-t-il la transaction? Si cela ne se produit pas, dois-je envoyer une deuxième commande pour l'annuler?

Je peux donner des détails sur l'API et la langue que j'utilise, mais je pense que SQL Server devrait répondre de la même manière, quelle que soit la langue.

179
jonathanpeppers

Vous pouvez mettre set xact_abort on avant votre transaction pour vous assurer que SQL s’annule automatiquement en cas d’erreur.

188
user121301

Vous avez raison de dire que toute la transaction sera annulée. Vous devez lancer la commande pour l'annuler.

Vous pouvez envelopper ceci dans un bloc TRY CATCH comme suit

BEGIN TRY
    BEGIN TRANSACTION

        INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
        INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
        INSERT INTO myTable (myColumns ...) VALUES (myValues ...);

    COMMIT TRAN -- Transaction Success!
END TRY
BEGIN CATCH
    IF @@TRANCOUNT > 0
        ROLLBACK TRAN --RollBack in case of Error

    -- you can Raise ERROR with RAISEERROR() Statement including the details of the exception
    RAISERROR(ERROR_MESSAGE(), ERROR_SEVERITY(), 1)
END CATCH
179
Raj More

Voici le code avec lequel le message d'erreur fonctionne avec MSSQL Server 2016:

BEGIN TRY
    BEGIN TRANSACTION 
        -- Do your stuff that might fail here
    COMMIT
END TRY
BEGIN CATCH
    IF @@TRANCOUNT > 0
        ROLLBACK TRAN

        DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE()
        DECLARE @ErrorSeverity INT = ERROR_SEVERITY()
        DECLARE @ErrorState INT = ERROR_STATE()

    -- Use RAISERROR inside the CATCH block to return error  
    -- information about the original error that caused  
    -- execution to jump to the CATCH block.  
    RAISERROR (@ErrorMessage, -- Message text.  
               @ErrorSeverity, -- Severity.  
               @ErrorState -- State.  
               );
END CATCH
32
samwise

Extrait de l'article MDSN, Contrôle des transactions (moteur de base de données) .

Si une erreur d'instruction au moment de l'exécution (telle qu'une violation de contrainte) se produit dans un lot, le comportement par défaut du moteur de base de données consiste à annuler uniquement l'instruction qui a généré l'erreur. Vous pouvez modifier ce comportement à l'aide de l'instruction SET XACT_ABORT. Une fois que SET XACT_ABORT ON est exécuté, toute erreur d’instruction au moment de l’exécution entraîne une annulation automatique de la transaction en cours. Les erreurs de compilation, telles que les erreurs de syntaxe, ne sont pas affectées par SET XACT_ABORT. Pour plus d'informations, consultez SET XACT_ABORT (Transact-SQL).

Dans votre cas, la transaction complète sera annulée en cas d'échec d'une des insertions.

21
Vitaly

Si l'une des insertions échoue ou si une partie de la commande échoue, le serveur SQL annule-t-il la transaction?

Non.

Si cela ne se produit pas, dois-je envoyer une deuxième commande pour l'annuler?

Bien sûr, vous devriez utiliser ROLLBACK au lieu de COMMIT.

Si vous souhaitez décider de valider ou d’annuler la transaction, vous devez supprimer la phrase COMMIT de l’instruction, vérifier les résultats des insertions, puis émettre soit COMMIT ou ROLLBACK selon sur les résultats du contrôle.

10
Quassnoi