Was bedeuten die verschiedenen Schweregrade von RAISERROR?

74

Mein bestes Google - Ergebnis war diese :

  • Unter 11 sind Warnungen, keine Fehler
  • 11-16 stehen zur Verfügung
  • über 16 sind Systemfehler
  • Es gibt keinen Verhaltensunterschied zwischen 11-16

In BOL können jedoch "Schweregrade von 0 bis 18 von jedem Benutzer angegeben werden".

In meiner speziellen gespeicherten Prozedur möchte ich, dass der Fehler an eine .NET-Clientanwendung zurückgegeben wird. Es sieht also so aus, als würde ein Schweregrad zwischen 11 und 18 den Trick ausführen. Hat jemand maßgebliche Informationen darüber, was die einzelnen Ebenen bedeuten und wie sie verwendet werden sollten?

Steve S.
quelle
2
Ich weiß es nicht für andere Versionen, aber ich war sehr überrascht zu sehen, dass mit SQL Server 2008 der Schweregrad 16 die Ausführung NICHT beendet.
Ich verwende den gleichen Trick für eine Delphi-Anwendung. Nach Versuch und Irrtum verwende ich Level = 13. Auf diese Weise wird die Ausführung nicht gestoppt (ich erhebe den Fehler in einem Trigger, um dem Benutzer Informationen anzuzeigen) und der Benutzer erhält die Nachricht. Natürlich ist es eine "schrecklich schlechte Praxis", aber effektiv.
LaBracca
"Schreckliche schlechte Praktiken" sind notwendig, um viele, viele, viele MS-Hindernisse zu umgehen. Das Umgehen von MS-Hindernissen ist jedoch normalerweise eine "gute Praxis".
Umgekehrter Ingenieur

Antworten:

107

Schweregrade der Datenbank-Engine

Sie sollten 16 zurückgeben. Ist die am häufigsten verwendete Standardfehlerstufe:

Zeigt allgemeine Fehler an, die vom Benutzer korrigiert werden können.

Geben Sie nicht 17-18 zurück, diese weisen auf schwerwiegendere Fehler wie Ressourcenprobleme hin:

Zeigen Sie Softwarefehler an, die vom Benutzer nicht korrigiert werden können. Informieren Sie Ihren Systemadministrator über das Problem.

Geben Sie auch nicht 11-15 zurück, da diese jeder Ebene eine besondere Bedeutung haben (14 - Sicherheitszugriff, 15 - Syntaxfehler, 13 - Deadlock usw.).

Level 16 beendet die Ausführung nicht.

Wenn Sie eine Warnung protokollieren und die Ausführung fortsetzen möchten, verwenden Sie stattdessen einen Schweregrad unter 10.

Remus Rusanu
quelle
Der MSDN-Link sagt irgendwie alles - die Informationen waren genau dort in BOL, und ich habe sie noch nie gesehen. Vielen Dank!
Steve S.
1
Wenn Sie "Standard" sagen, bedeutet dies, dass eine Fehlerstufe von 16 verwendet wird, wenn ich RAISERROR aufrufe und keine Parameter übergebe. dh es wird von einem Fangblock gefangen?
Triynko
3
Level 16 beendet die Ausführung nicht. Siehe stackoverflow.com/questions/76346/… . Wenn ich nichts verpasst habe, möchten Sie möglicherweise Ihre Antwort aktualisieren.
McNux
Ein Fremdschlüsselverletzungsfehler hat auch den Schweregrad 16. Andere Datenintegritätsfehler können ebenfalls diesen Schweregrad haben, ich weiß nicht, aber wenn Sie Fehler "Geschäftsregeln" auslösen und behandeln, kann 16 irreführend sein. In meinem Fall habe ich Parameter für den Erfolg (wahr oder falsch) und die Fehlermeldung verwendet.
Raphael
1
@mcNux Ist absolut richtig, Level 16 beendet die gerade getestete Ausführung nicht sowohl auf SQL Server 2008 R2 als auch auf SQL Server 2012. Rollback-Bearbeitung .
Lankymart
7

Der Schweregrad 16 kann die Ausführung beenden.

Vorsichtsmaßnahmen beim Versuch mit RAISERROR ():

RAISERROR()mit einem Schweregrad von 16 wird die Ausführung für alles unterhalb der betreffenden Linie beendet.
Doch dies nur gilt , wenn innerhalb eines Try-Blöcke.

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

Überrascht? So war I.
Was warf mich auch für eine Schleife nicht alle Severity- ist 16 ‚s gleich sind.
Wenn Sie die Divide-By-Zero-Linie ganz oben auskommentieren würden, würde nichts darunter laufen.
The Divide-By-Zero - Logik wird auch erzeugen eine Severity- 16 Ausnahme,
  aber es ist mit einem handVollAnschlag , anders als wenn sie geworfen mit RAISERROR().

Hinweis: Verwenden Sie diese Option ;THROWals letzte Zeile in Ihrem Catch-Block, um
           die SQL-Ausnahme für das RAISERROR()von Ihrem Try-Block ausgelöste Ereignis ordnungsgemäß auszulösen.
           Dadurch wird die Ausführung effektiv mit einem Punkt gestoppt.
           Das ;Semikolon ist erforderlich, wenn vor dem Aufruf andere Zeilen im Catch-Block vorhanden sind ;THROW.
Wenn Ihre Logik richtig den Fehler in dem Catch - Block behandelt (und Sie würden die Verarbeitung fortfahren ,
  den Rest der Logik , nachdem es), dann kann nicht verwendet werden ;THROW.

Fazit:

Kombinieren Sie einen von der SQL-Server-Engine ausgelösten Schweregrad 16 nicht
  mit einem, den Sie selbst erhöhen RAISERROR().
Berücksichtigen Sie in jeder Hinsicht (wenn Sie absichtlich Ihre eigenen Fehler auslösen) nur 2 Schweregrade:
    0 (zur Information oder Warnung) und
  16 (zum Auslösen einer Ausnahme, die in einem Try-Block behandelt wird - um sie in den Catch-Block zu werfen). .

Informationen jetzt!

Hinweis: Wenn Sie RAISERROR()zum Anzeigen von Informationsnachrichten verwenden,
           empfehle ich Folgendes 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

Dies ist besonders nützlich bei langen Batch-Vorgängen, wenn Sie einen Einblick
  in den Fortschritt erhalten möchten, wenn Sie bestimmte Meilensteinmarkierungen im gesamten Batch erreichen.
Wenn Sie nicht verwenden WITH NOWAIT, wissen Sie möglicherweise nie, wann Ihre Informationsnachrichten angezeigt werden.
Sie können zeitweise im Verlauf der Charge oder auf einmal auftreten, wenn die Charge abgeschlossen ist.

MikeTeeVee
quelle
Endet nicht auf SQL 2016 auch mit dem@divideByZero
Mike