Dans les procédures stockées, il est possible et nécessaire de gérer les erreurs à l'aide de constructions spéciales.
Dans SQL Server, les principaux mécanismes sont les blocs TRY...CATCH, où toutes les erreurs à l'intérieur du TRY sont capturées, et dans le CATCH, on peut enregistrer les détails. Des fonctions comme ERROR_NUMBER(), ERROR_MESSAGE() sont disponibles pour obtenir les détails.
BEGIN TRY -- Opération risquée UPDATE Accounts SET balance = balance - 100 WHERE id = 1; END TRY BEGIN CATCH INSERT INTO ErrorLog( ErrorTime, ErrorNumber, ErrorMessage, UserName ) VALUES ( GETDATE(), ERROR_NUMBER(), ERROR_MESSAGE(), SUSER_SNAME() ); -- Restaurer ou ROLLBACK supplémentaire END CATCH
Dans Oracle, on utilise plus souvent des blocs EXCEPTION :
BEGIN UPDATE ...; EXCEPTION WHEN OTHERS THEN INSERT INTO error_log VALUES (..., SQLERRM); END;
Points à garder à l'esprit :
Une exception dans un bloc CATCH peut-elle entraîner une perte de contexte d'erreur ? Comment réaliser un traitement d'erreur imbriqué ?
Réponse et exemple : Si une erreur se produit dans le bloc CATCH (par exemple, en raison de l'indisponibilité de la table ErrorLog), le contexte d'erreur d'origine est perdu, et l'information sur la cause de l'échec peut être perdue.
Pour se prémunir, encapsulez la journalisation dans une procédure distincte avec son propre TRY...CATCH, afin de toujours capturer "l'erreur dans le gestionnaire d'erreurs".
BEGIN TRY -- code principal END TRY BEGIN CATCH EXEC LogError @Error = ERROR_MESSAGE(); END CATCH -- La procédure LogError contient elle-même son propre TRY...CATCH
Histoire
Projet : Rapport financier. Dans les procédures stockées, des blocs TRY...CATCH ont été ajoutés, mais les paramètres avec lesquels l'erreur s'est produite n'ont pas été journalisés. En conséquence, lors de la capture de pannes critiques, il a fallu chercher manuellement la situation dans la sauvegarde - la cause profonde n'était pas évidente.
Histoire
Projet : Automatisation de la gestion documentaire (Oracle). Dans le bloc EXCEPTION, nous avons oublié de journaliser le nom d'utilisateur. Après une semaine d'enquête, nous avons découvert que quelqu'un "piratait" délibérément des documents - nous l'avons découvert uniquement par des indices indirects dans le journal d'audit.
Histoire
Projet : E-commerce. La procédure, lors d'une erreur, écrivait dans ErrorLog. Un jour, la table Log a été bloquée par une transaction envahissante, et la tentative de journalisation a entraîné une erreur imbriquée, qui a écrasé la cause originale et nettoyé la pile d'erreurs. Nous avons corrigé cela en intégrant une table supplémentaire pour les pannes critiques et un journal multi-niveaux.