ProgrammationDéveloppeur de bases de données

Comment mettre en œuvre des procédures efficaces de gestion des erreurs et de débogage dans les procédures stockées SQL ? Quels mécanismes sont prévus pour capturer et journaliser les erreurs ? Ces approches diffèrent-elles dans différentes SGBD ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

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 :

  • Toutes les erreurs ne sont pas gérées par CATCH, par exemple, les erreurs de parsing ou de compilation feront échouer la transaction avant d'entrer dans TRY.
  • Pour journaliser des informations, il est important d'avoir une table distincte pour les erreurs.
  • Il vaut la peine de journaliser autant que possible : le texte de l'erreur, le numéro, le nom d'utilisateur, les paramètres de l'opération.
  • La syntaxe et les possibilités diffèrent selon les SGBD.

Question piège.

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.