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é.
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".