Ich habe ein Verhalten THROW
, das ich nicht verstehen kann. Betrachten Sie die folgende gespeicherte Prozedur:
CREATE PROCEDURE usp_division_err AS
SET NOCOUNT ON;
BEGIN TRY
EXEC('select 1/0')
END TRY
BEGIN CATCH
THROW;
END CATCH
Wenn die Prozedur ausgeführt wird, wird der folgende Fehler ausgelöst:
Meldung 8134, Ebene 16, Status 1, Zeile 1
Fehler beim Teilen durch Null aufgetreten.
Beachten Sie, dass keine Informationen darüber enthalten sind, in welcher Prozedur der Fehler ausgelöst wurde. Das liegt daran, dass das fehlerhafte, dynamische SQL in einem anderen Bereich ausgeführt wird, und das ist in Ordnung. Ändern Sie den CATCH
-block jedoch so, dass er so aussieht
BEGIN CATCH
THROW 50000, 'An error occurred.', 1;
END CATCH
und die Ausführung der Prozedur löst stattdessen diesen Fehler aus:
Meldung 50000, Ebene 16, Status 1, Prozedur usp_division_err, Zeile 7 [Stapelstartzeile 0]
Ein Fehler ist aufgetreten.
Der Fehler tritt immer noch beim Ausführen des dynamischen SQL auf, aber wenn ich die Fehlernummer und die Fehlermeldung (der erste und zweite Parameter von THROW
) manuell spezifiziere , wird der Prozedurname der ausführenden Prozedur irgendwie angezeigt.
Warum erscheint der Prozedurname in der zweiten Fehlermeldung, aber nicht in der ersten?
quelle
FORMATMESSAGE
in meinem äußersten Wurf, um den SP-Namen anzuhängen die Nachricht mitOBJECT_NAME(@@PROCID)
.Antworten:
Code
CATCH
wie folgt:Auf diese Weise können Sie alle Parameter an die
THROW
Anweisung übergeben, um sie an den Aufrufer zurückzusenden.Ich habe das so getestet:
Die Ergebnisse:
Um die native Fehlernummer zu erhalten, müssen Sie nur 50000 von der gemeldeten Fehlernummer abziehen. Da die Parameter für
THROW
optional sind, müssen zwei Codepfade enthalten seinTHROW
, einer, der den Prozedurnamen angibt, und einer, der dies nicht tut. Ich überlasse es dem Leser zu entscheiden, welcher Codepfad das tut.quelle