Historiquement, la gestion des erreurs en SQL était limitée au rollback de la transaction après une erreur fatale. Cependant, avec l’évolution de la logique métier, il est de plus en plus nécessaire de consigner les erreurs avec précision, de rollback uniquement les modifications qui ont été effectuées, ainsi que de permettre l'imbrication des appels de procédures (nested transactions).
Le problème réside dans le fait que toutes les SGBD ne supportent pas pleinement les transactions imbriquées (par exemple, dans MS SQL Server, il s’agit plutôt de niveaux de points de sauvegarde SAVEPOINT que de vraies transactions), et les exceptions en cas d'erreurs peuvent interrompre l'exécution avant le nettoyage nécessaire si les mécanismes TRY/CATCH ou analogues ne sont pas utilisés.
Solution : utiliser des constructions TRY/CATCH (ou similaires), SAVEPOINT pour l’imbrication, et configurer le comportement des procédures en cas d'erreurs (par exemple, SET XACT_ABORT dans SQL Server).
Exemple de code (MS SQL Server) :
BEGIN TRY BEGIN TRANSACTION -- opérations EXEC dbo.InnerProcedure COMMIT TRANSACTION END TRY BEGIN CATCH IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION -- journalisation de l'erreur INSERT INTO error_log VALUES (ERROR_NUMBER(), ERROR_MESSAGE(), GETDATE()) END CATCH
Caractéristiques clés :
En cas d'erreur dans une transaction imbriquée, les modifications sont-elles réellement annulées ?
Dans la plupart des SGBD, les transactions imbriquées ne sont pas des transactions distinctes, mais des points de retour (SAVEPOINT). Lors d'un rollback général, toutes les modifications sont annulées jusqu'à la transaction initiale (outer).
Que se passe-t-il si vous oubliez de vérifier @@TRANCOUNT et que vous exécutez ROLLBACK en dehors d’une transaction active ?
Une erreur sera déclenchée — aucune transaction active pour le rollback. Vérifiez toujours @@TRANCOUNT > 0 avant de faire un ROLLBACK.
Les triggers et curseurs fonctionnent-ils dans TRY/CATCH ?
Oui, mais les erreurs dans un trigger peuvent provoquer un passage à CATCH et annuler l’ensemble de la transaction. Il est nécessaire de prévoir la gestion des erreurs tant dans le corps de la procédure que dans les objets appelés (procédures, triggers).
Plusieurs procédures imbriquées, chacune utilisant BEGIN TRANSACTION / COMMIT sans TRY/CATCH, en cas d'erreur, une partie des données a été modifiée, une autre non.
Avantages :
Inconvénients :
Toute la logique est enveloppée dans TRY/CATCH, les procédures imbriquées utilisent SAVEPOINT ou opèrent dans une seule transaction externe, toutes les erreurs sont enregistrées.
Avantages :
Inconvénients :