78 votes

Que signifient les différents niveaux de gravité de RAISERROR ?

Mon meilleur résultat sur Google était este :

  • les 11 ci-dessous sont des avertissements et non des erreurs
  • 11-16 sont disponibles pour l'utilisation
  • au-dessus de 16 sont des erreurs de système
  • il n'y a pas de différence de comportement entre les 11-16

Mais, d'après BOL, "Les niveaux de gravité de 0 à 18 peuvent être spécifiés par n'importe quel utilisateur."

Dans ma procédure stockée particulière, je veux que l'erreur soit renvoyée à une application client .Net, donc il semble que n'importe quel niveau de gravité entre 11 et 18 fasse l'affaire. Quelqu'un dispose-t-il d'informations fiables sur la signification de chacun de ces niveaux et sur la manière de les utiliser ?

4 votes

Je ne sais pas pour les autres versions mais j'ai été très surpris de voir qu'avec SQL Server 2008, la sévérité 16 fait PAS mettre fin à l'exécution.

0 votes

J'utilise la même astuce pour une application Delphi, après des essais et des erreurs, j'utilise le niveau = 13. De cette façon, l'exécution n'est pas interrompue (je lève l'erreur dans un trigger pour afficher l'information à l'utilisateur) et l'utilisateur reçoit le message. Bien sûr, il s'agit d'une "terrible mauvaise pratique", mais elle est efficace.

0 votes

De "terribles mauvaises pratiques" sont nécessaires pour contourner de très, très, très nombreux obstacles liés à la SEP. En revanche, contourner les obstacles de la SEP est généralement une "bonne pratique".

110voto

Remus Rusanu Points 159382

Niveaux de gravité du moteur de base de données

Vous devriez retourner 16. C'est le niveau d'erreur par défaut, le plus utilisé :

Indique des erreurs générales qui peuvent être être corrigées par l'utilisateur.

Ne renvoyez pas 17-18, ceux-ci indiquent des erreurs plus graves, comme des problèmes de ressources :

Indique des erreurs logicielles qui ne peuvent pas être corrigées par l'utilisateur. Informez votre administrateur système du problème.

Ne renvoyez pas non plus les niveaux 11 à 15, car ils ont une signification particulière (14 - accès sécurisé, 15 - erreur de syntaxe, 13 - blocage, etc.)

Le niveau 16 ne met pas fin à l'exécution.

Lorsque votre intention est d'enregistrer un avertissement mais de poursuivre l'exécution, utilisez plutôt un niveau de gravité inférieur à 10.

0 votes

Le lien MSDN dit en quelque sorte tout - l'information était juste là dans BOL, et je ne l'avais jamais vue avant. Merci !

1 votes

Lorsque vous dites "par défaut", voulez-vous dire qu'un niveau d'erreur de 16 sera utilisé si j'appelle RAISERROR, sans passer de paramètres, c'est-à-dire qu'il sera attrapé par un bloc catch ?

5 votes

Le niveau 16 ne met pas fin à l'exécution. Voir stackoverflow.com/questions/76346/ . À moins que j'aie manqué quelque chose, vous pourriez mettre à jour votre réponse.

9voto

MikeTeeVee Points 3578

Niveau de gravité 16 puede Mettre fin à l'exécution.

TRY-CATCH Avertissements avec RAISERROR() :

RAISERROR() avec une sévérité de 16 met fin à l'exécution de tout ce qui se trouve en dessous de la ligne incriminée.
Cependant ce uniquement s'applique à l'intérieur d'un bloc d'essai.

--DECLARE @DivideByZero Int = 1/0--Uncommenting this will Skip everything below.
RAISERROR (N'Before Try: Raise-Error 16.', 16, 0)--Works.
SELECT 'Before Try: Select.'[Marker]--Works.
BEGIN TRY
    RAISERROR (N'Inside Try: Raise-Error 16.', 16, 0)--Not displayed,but sends to Catch-Block.
    SELECT 'Inside Try: Select.'[Marker]--Skipped.
END TRY
BEGIN CATCH
    RAISERROR (N'Inside Catch: Raise-Error 16.', 16, 0)--Works.
    SELECT 'Inside Catch: Select.'[Marker]--Works.
    --RETURN --Adding Return will only skip what is After the Catch-Block for this scope only.
    --;THROW--Shows the RAISERROR() from the Try-Block and Halts Execution. Must include ";".
END CATCH
RAISERROR (N'After Try-Catch: Raise-Error 16.', 16, 0)--Works.
SELECT 'After Try-Catch: Select.'[Marker]--Works.

Surpris ? Moi aussi.
Ce qui m'a également surpris, c'est que tous les Severity- 16 sont les mêmes.
Si vous décommentez la ligne Divide-By-Zero tout en haut, rien de ce qui se trouve en dessous ne sera exécuté.
La logique de division par zéro également génère une sévérité- 16 Exception,
  mais il est traité avec un arrêt complet contrairement à ce qui se passe avec RAISERROR() .

Note : Utilisez ;THROW comme le dernier à l'intérieur de votre Catch-Block pour bien
           lance l'exception SQL pour le RAISERROR() événement déclenché par votre Try-Block.
           Cela arrêtera effectivement l'exécution avec un arrêt complet.
           Le site ; Le point-virgule est requis lorsque d'autres lignes existent dans le Catch-Block avant d'appeler ;THROW .
Si votre logique traite correctement l'erreur dans le Catch-Block (et que vous souhaitez poursuivre le traitement
  le reste de la logique après elle), puis faire no utiliser ;THROW .

Conclusion :

Ne pas confondre une sévérité 16 lancées par le moteur SQL-Server
  avec un que vous élevez vous-même en utilisant RAISERROR() .
À toutes fins utiles (lorsque vous lancez délibérément vos propres erreurs), ne considérez que deux sévérités :
    0 (pour Information ou Avertissement) et
  16 (pour le lancement d'une exception gérée à l'intérieur d'un bloc d'essai - pour la renvoyer vers le bloc d'arrêt).

Information maintenant !

Note : Si vous utilisez RAISERROR() pour afficher les messages d'information,
           alors je suggère d'utiliser WITH NOWAIT :

RAISERROR('Read me right now!', 0, 1) WITH NOWAIT
RAISERROR('Read me whenever.' , 0, 1)
DECLARE @WaitSeconds Int = 10
DECLARE @WaitFor DateTime = DATEADD(SECOND, @WaitSeconds, 0)
WAITFOR DELAY @WaitFor

Ceci est particulièrement utile lors de longues opérations par lots, lorsque vous souhaitez avoir un aperçu de la situation.
  pour savoir comment les choses progressent à mesure que vous atteignez certains jalons tout au long du lot.
Par no en utilisant WITH NOWAIT vous ne savez jamais quand vos messages d'information peuvent apparaître.
Ils peuvent apparaître par intermittence tout au long du lot, ou tous en même temps lorsque le lot est terminé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X