Implémenter la gestion des erreurs T-SQL

Effectué

Une erreur indique un problème ou un problème notable qui se produit pendant une opération de base de données. Les erreurs peuvent être générées par le moteur de base de données SQL Server en réponse à un événement ou une défaillance au niveau du système ; ou vous pouvez générer des erreurs d’application dans votre code Transact-SQL.

Éléments des erreurs du moteur de base de données

Quelle que soit la cause, chaque erreur se compose des éléments suivants :

  • Numéro d’erreur : numéro unique identifiant l’erreur spécifique.
  • Message d’erreur : texte décrivant l’erreur.
  • Gravité : indication numérique de la gravité de 1 à 25.
  • État : code d’état interne pour la condition du moteur de base de données.
  • Procédure : nom de la procédure stockée ou du déclencheur dans lequel l’erreur s’est produite.
  • Numéro de ligne - Quelle instruction dans le lot ou la procédure a généré l’erreur.

Erreurs système

Les erreurs système sont prédéfinies et vous pouvez les afficher dans la vue système sys.messages . Lorsqu’une erreur système se produit, SQL Server peut prendre des mesures correctives automatiques, en fonction de la gravité de l’erreur. Par exemple, lorsqu’une erreur de gravité élevée se produit, SQL Server peut mettre une base de données hors connexion ou même arrêter le service du moteur de base de données.

Erreurs personnalisées

Vous pouvez générer des erreurs dans Transact-SQL code pour répondre à des conditions spécifiques à l’application ou personnaliser les informations envoyées aux applications clientes en réponse aux erreurs système. Ces erreurs d’application peuvent être définies inline où elles sont générées, ou vous pouvez les prédéfinir dans la table sys.messages en même temps que les erreurs fournies par le système. Les numéros d’erreur utilisés pour les erreurs personnalisées doivent être 50001 ou ultérieur.

Pour ajouter un message d’erreur personnalisé à sys.messages, utilisez sp_addmessage. L’utilisateur du message doit être membre des rôles serveur fixes sysadmin ou serveradmin.

Il s’agit de la syntaxe sp_addmessage :

sp_addmessage [ @msgnum= ] msg_id , [ @severity= ] severity , [ @msgtext= ] 'msg' 
     [ , [ @lang= ] 'language' ] 
     [ , [ @with_log= ] { 'TRUE' | 'FALSE' } ] 
     [ , [ @replace= ] 'replace' ]

Voici un exemple de message d’erreur personnalisé à l’aide de cette syntaxe :

sp_addmessage 50001, 10, N’Unexpected value entered’;

En outre, vous pouvez définir des messages d’erreur personnalisés, les membres du rôle serveur sysadmin peuvent également utiliser un paramètre supplémentaire, @with_log. Lorsqu’elle est définie sur TRUE, l’erreur est également enregistrée dans le journal des applications Windows. Tout message écrit dans le journal des applications Windows est également écrit dans le journal des erreurs SQL Server. Soyez judicieux d’utiliser l'option @with_log, car les administrateurs réseau et système ont tendance à ne pas se prévaloir des applications qui sont « bavardes » dans les journaux système. Toutefois, si l’erreur doit être interceptée par une alerte, l’erreur doit d’abord être écrite dans le journal des applications Windows.

Remarque

Le déclenchement d’erreurs système n’est pas pris en charge.

Les messages peuvent être remplacés sans les supprimer d’abord à l’aide de l’option @replace = 'replace'.

Les messages sont personnalisables et différents peuvent être ajoutés pour le même numéro d’erreur pour plusieurs langues, en fonction d’une valeur language_id.

Remarque

Les messages anglais sont language_id 1033.

Déclencher des erreurs à l’aide de RAISERROR

PRINT et RAISERROR peuvent être utilisés pour renvoyer des informations ou des messages d’avertissement aux applications. RAISERROR permet aux applications de déclencher une erreur qui peut ensuite être interceptée par le processus appelant.

RAISERROR

La possibilité de déclencher des erreurs dans T-SQL facilite la gestion des erreurs dans l’application, car elle est envoyée comme toute autre erreur système. RAISERROR est utilisé pour :

  • Aidez à résoudre les problèmes de code T-SQL.
  • Vérifiez les valeurs des données.
  • Retourne des messages qui contiennent du texte variable.

Remarque

L’utilisation d’une instruction PRINT est similaire à la génération d’une erreur de sévérité 10.

Voici un exemple de message d’erreur personnalisé à l’aide de RAISERROR.

RAISERROR (N'%s %d', -- Message text,
    10, -- Severity,
    1, -- State,
    N'Custom error message number',
    2)

Lorsqu’elle est déclenchée, elle retourne :

Custom error message number 2

Dans l’exemple précédent, %d est un espace réservé pour un nombre et %s est un espace réservé pour une chaîne. En outre, vous devez noter qu’un numéro de message n’a pas été mentionné. Lorsque des erreurs avec des chaînes de message sont déclenchées à l’aide de cette syntaxe, elles ont toujours le numéro d’erreur 50000.

Déclencher des erreurs à l’aide de THROW

L’instruction THROW offre une méthode plus simple pour déclencher des erreurs dans le code. Les erreurs doivent avoir un nombre d’erreurs d’au moins 5 0000.

THROW

THROW diffère de RAISERROR de plusieurs façons :

  • Les erreurs générées par THROW sont toujours de gravité 16.
  • Les messages retournés par THROW ne sont liés à aucune entrée dans sys.sysmessages.
  • Les erreurs générées par THROW provoquent uniquement l’abandon des transactions lorsqu’elles sont utilisées conjointement avec SET XACT_ABORT ON et que la session est arrêtée.
THROW 50001, 'An Error Occured',0

Capturer des codes d’erreur à l’aide de @@Error

La plupart des codes de gestion des erreurs traditionnels dans les applications SQL Server ont été créés à l’aide de @@ERROR. La gestion structurée des exceptions a été introduite dans SQL Server 2005 et offre une alternative forte à l’utilisation de @@ERROR. Il sera abordé dans la leçon suivante. Une grande quantité de code de gestion des erreurs SQL Server existant est basée sur @@ERROR. Il est donc important de comprendre comment l’utiliser.

@@ERROR

@@ERROR est une variable système qui contient le numéro d’erreur de la dernière erreur qui s’est produite. Un défi important avec @@ERROR est que la valeur qu’il contient est rapidement réinitialisée à mesure que chaque instruction supplémentaire est exécutée.

Considérons par exemple le code suivant :

RAISERROR(N'Message', 16, 1);
IF @@ERROR <> 0
PRINT 'Error=' + CAST(@@ERROR AS VARCHAR(8));
GO

Vous pouvez vous attendre à ce que, lorsque le code est exécuté, il retourne le numéro d’erreur dans une chaîne imprimée. Toutefois, lorsque le code est exécuté, il retourne :

Msg 50000, Level 16, State 1, Line 1
Message
Error=0

L’erreur a été déclenchée, mais le message imprimé était « Error=0 ». Dans la première ligne de la sortie, vous pouvez voir que l’erreur, comme prévu, était en fait 50000, avec un message transmis à RAISERROR. Cela est dû au fait que l’instruction IF qui suit l’instruction RAISERROR a été exécutée correctement et a provoqué la réinitialisation de la valeur @@ERROR. Pour cette raison, lorsque vous travaillez avec @@ERROR, il est important de capturer le numéro d’erreur dans une variable dès qu’elle est levée, puis de continuer à traiter la variable.

Examinez le code suivant qui illustre ceci :

DECLARE @ErrorValue int;
RAISERROR(N'Message', 16, 1);
SET @ErrorValue = @@ERROR;
IF @ErrorValue <> 0
PRINT 'Error=' + CAST(@ErrorValue AS VARCHAR(8));

Lorsque ce code est exécuté, il retourne la sortie suivante :

Msg 50000, Level 16, State 1, Line 2
Message
Error=50000

Le numéro d’erreur est signalé correctement maintenant.

Centralisation de la gestion des erreurs

Un autre problème important lié à l’utilisation de @@ERROR pour la gestion des erreurs est qu’il est difficile de centraliser dans votre code T-SQL. La gestion des erreurs tend à se retrouver dispersée dans tout le code. Il serait possible de centraliser la gestion des erreurs à l’aide de @@ERROR dans une certaine mesure, à l’aide d’étiquettes et d’instructions GOTO. Toutefois, cela serait désapprouvé par la plupart des développeurs aujourd’hui comme une mauvaise pratique de codage.

Créer des alertes d’erreur

Pour certaines catégories d’erreurs, les administrateurs peuvent créer des alertes SQL Server, car ils souhaitent être avertis dès qu’ils se produisent. Cela peut même s’appliquer aux messages d’erreur définis par l’utilisateur. Par exemple, vous pouvez déclencher une alerte chaque fois qu’un journal des transactions se remplit. Les alertes sont couramment utilisées pour attirer l’attention des administrateurs sur les erreurs de gravité élevée (par exemple, la gravité 19 ou ultérieure).

Déclenchement d’alertes

Les alertes peuvent être créées pour des messages d’erreur spécifiques. Le service d’alerte fonctionne en s’inscrivant en tant que service de rappel auprès du service de journalisation des événements. Cela signifie que les alertes fonctionnent uniquement sur les erreurs journalisées.

Il existe deux méthodes pour faire en sorte qu'une erreur génère une alerte : vous pouvez utiliser l'option WITH LOG lors du déclenchement de l'erreur, ou le message peut être modifié pour être consigné en exécutant sp_altermessage. L’option WITH LOG affecte uniquement l’instruction active. L’utilisation de sp_altermessage modifie le comportement d’erreur pour toute utilisation ultérieure. La modification des erreurs système via sp_altermessage est possible uniquement à partir de SQL Server 2005 SP3 ou SQL Server 2008 SP1.