ProgrammationDéveloppeur SQL

Comment mettre en œuvre une gestion fiable des exceptions (Exception Handling) et un rollback des transactions dans des procédures stockées SQL, en particulier dans le scénario des transactions imbriquées (Nested) ? Quelles sont les limitations et les particularités de telles solutions ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

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 :

  • Utilisation de TRY/CATCH pour intercepter les erreurs.
  • Contrôle de @@TRANCOUNT pour l’imbrication.
  • SAVEPOINT (ou analogues manuels pour le contrôle du retour à un point).

Questions piégées.

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).

Erreurs typiques et anti-patterns

  • Absence de vérification de @@TRANCOUNT — tentative d’annuler une transaction inactive.
  • Engagements ou rollbacks superflus dans les niveaux imbriqués.
  • Journalisation des erreurs sans conserver tous les détails (numéro, texte, paramètres).

Exemple de la vie réelle

Cas négatif

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 :

  • Code simple

Inconvénients :

  • Désynchronisation d'état
  • Erreurs non évidentes après une panne

Cas positif

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 :

  • Intégrité complète
  • Audit des erreurs

Inconvénients :

  • Script plus encombrant
  • Un peu plus difficile à maintenir la logique d'auto-enregistrement.