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.
Vous pouvez mettre set xact_abort on
avant votre transaction pour vous assurer que SQL s’annule automatiquement en cas d’erreur.
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
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
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.
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.