SQL Server-Fehlerbehandlung und TRY CATCH
- 24-07-2022
- Toanngo92
- 0 Comments
Mục lục
Einführen
Die Fehlerbehandlung in SQL Server ist jetzt durch verschiedene Techniken einfacher.
SQL Server hat Optionen eingeführt, mit denen Benutzer Fehler effektiver kontrollieren können
Normalerweise kann der Endbenutzer den Fehler, der auf der Anwendungsseite auftritt, nicht erkennen.
Daher bietet SQL Server eine TRY … CATCH-Anweisung für eine effizientere Fehlerkontrolle am Backend.
Einige Systemfunktionen können relevante Informationen zum Fehler ausdrucken, was die Behebung des Fehlers erleichtert.
Arten von Fehlern
T-SQL-Programmierer müssen sich der Fehlertypen bewusst sein, die bei der Arbeit mit SQL Server-Anweisungen auftreten. Der erste Schritt besteht darin, die Art des Fehlers zu identifizieren und dann herauszufinden, wie mit dem Fehler umzugehen ist.
Liste der Fehlertypen
Syntaxfehler
Ein Syntaxfehler tritt auf, wenn der Code syntaktisch falsch ist und von SQL Server nicht verstanden werden kann. Diese Fehler werden von SQL Server erkannt, bevor die Ausführung des T-SQL-Blocks oder der gespeicherten Prozedur beginnt.
Wenn der Benutzer die falschen Schlüsselwörter oder Operationen eingibt, weil er sich nicht an die gültige Syntax erinnert, weist der Code-Editor darauf hin.
Wenn der Benutzer vergisst, ein Schlüsselwort einzugeben, oder eine Aktion erforderlich ist, um den Befehl abzuschließen, meldet der Code-Editor einen Fehler, wenn der Benutzer den Befehl ausführt.
Syntaxfehler (Syntaxfehler) sind leicht zu identifizieren, da der Code-Editor darauf hinweist. Wenn Sie jedoch eine Befehlszeilenanwendung verwenden, wird der Fehler erst angezeigt, nachdem der Benutzer den Befehl ausgeführt hat.
Laufzeitfehler
Ein Laufzeitfehler tritt auf, wenn eine Anwendung versucht, eine Aufgabe zu verarbeiten, die von SQL Server oder dem Betriebssystem nicht unterstützt wird.
Einige Laufzeitfehler, die auftreten können, sind wie folgt:
- Behandeln Sie die Berechnung der Division durch 0
- Versucht, Code auszuführen, der nicht explizit definiert ist. (Das folgende Beispiel zeigt eine Situation, in der der Wert größer ist, als der Datentyp darstellen kann).
Häufige Situationen, in denen Laufzeitfehler auftreten:
- Verwenden Sie gespeicherte Prozeduren, Funktionen oder Trigger, die nicht verfügbar (gelöscht) sind.
- Versuch, eine Aufgabe zu verarbeiten, die auf ein Objekt oder eine Variable angewendet wird, die nicht verarbeitet werden kann (Tabelle gelöscht, nicht in der Datenbank …)
- Die Situation des Ram-Überlaufs (Stapelüberlauf), wenn die Anwendung überlastet ist
- Versuchen Sie, Aufgaben mit inkompatiblen Datentypen zu bearbeiten.
- Missbrauch von bedingten Anweisungen.
Fehlerbehandlung implementieren
Im Softwareentwicklungsprozess ist es unter anderem wichtig, auf die Fehlerbehandlung zu achten. In gewisser Weise müssen sich Benutzer beim Entwerfen der Datenbank um die Behandlung von Ausnahmen kümmern. Es können verschiedene Verarbeitungsmechanismen verwendet werden.
- Beim Ausführen von DML-Anweisungen wie INSERT, DELETE, UPDATE können Benutzer Fehler behandeln, um eine korrekte Ausgabe sicherzustellen.
- Wenn die Transaktion fehlschlägt und der Benutzer die Transaktion rückgängig machen muss, sollte dem Benutzer eine entsprechende Fehlermeldung angezeigt werden.
- Beim Arbeiten mit Cursorn in SQL Server können Benutzer Fehler behandeln, um genaue Ergebnisse sicherzustellen.
TRY … CATCH-Befehlsblock
Der TRY … CATCH-Block wird verwendet, um die Ausnahmebehandlung in Transact SQL zu implementieren. Ein oder mehrere T-SQL-Befehle sind durch einen TR-Block begrenzt. Wenn in einem TRY-Block ein Fehler auftritt, fließt die Steuerung zu einem catch-Block, der eine oder mehrere Anweisungen innerhalb des CATCH-Blocks enthalten kann.
Syntax:
BEGIN TRY {sql_statement | statement_block} END TRY BEGIN CATCH [ {sql_statement | statement_block}] END CATCH [;]
Zum Beispiel:
BEGIN TRY DECLARE @num int; SELECT @num=217/0; END TRY BEGIN CATCH PRINT 'Error occurred, unable to devide by 0' END CATCH;
Fehlerinformationen
Die beste Lösung besteht darin, die Fehlerinformationen zusammen mit dem Fehler anzuzeigen, damit der Fehler schnell und effizient behoben werden kann.
Dazu müssen Systemfunktionen innerhalb des CATCH-Blocks verwendet werden, um Informationen über den Fehler zu finden, der bei der Ausführung des Blocks generiert wird.
Liste der Systemfunktionen, die Fehlerinformationen liefern:
- ERROR_NUMBER() : gibt die Fehlernummer zurück.
- ERROR_SERVERITY() : Schweregrad zurückgeben
- ERROR_STATE(): gibt die Fehlerstatusnummer zurück.
- ERROR_PROCEDURE(): Gibt den Namen des Triggers oder der gespeicherten Prozedur zurück, die den Fehler verursacht hat.
- ERROR_LINE(): gibt die Anzahl der Zeilen zurück, die den Fehler verursacht haben
- ERROR_MESSAGE(): gibt den vollständigen Text des Fehlers zurück, der Text enthält die als Parameter bereitgestellten Werte wie Objektnamen, Länge.
Diese Funktionen geben NULL zurück, wenn sie außerhalb des CATCH-Blocks aufgerufen werden
Verwenden Sie TRY…CATCH mit Fehlerinformationen
USE AdventureWorks2019; GO BEGIN TRY SELECT 217/0; END TRY BEGIN CATCH SELECT ERROR_NUMBER() AS ErrorNumer, ERROR_SEVERITY() AS ErrorSeverity, ERROR_LINE() AS ErrorLine, ERROR_MESSAGE() AS ErrorMessage; END CATCH; GO
Eine gespeicherte Beispielprozedur enthält Fehlerbehandlungsfunktionen:
USE AdventureWorks2019; GO IF OBJECT_ID ('sp_ErrorInfo','P') IS NOT NULL DROP PROCEDURE sp_ErrorInfo; GO CREATE PROCEDURE sp_ErrorInfo AS SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_SEVERITY() AS ErrorSeverity, ERROR_STATE() AS ErrorState, ERROR_PROCEDURE() AS ErrorProcedure, ERROR_LINE() AS ErrorLine, ERROR_MESSAGE() AS ErrorMessage; GO BEGIN TRY SELECT 217/0 END TRY BEGIN CATCH EXEC sp_ErrorInfo; END CATCH
Verwenden von TRY…CATCH in der Transaktion
USE AdventureWorks2019; GO BEGIN TRANSACTION; BEGIN TRY DELETE FROM Production.Product WHERE ProductID = 980; END TRY BEGIN CATCH SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_SEVERITY() AS ErrorSeverity, ERROR_STATE() AS ErrorState, ERROR_PROCEDURE() AS ErrorProcedure, ERROR_LINE() AS ErrorLine, ERROR_MESSAGE() AS ErrorMessage; IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION; END CATCH; IF @@TRANCOUNT > 0 COMMIT TRANSACTION; GO
Unverbindliche Transaktion
Wenn vom TRY-Block ein Fehler generiert wird, wird dieser wirksam und die Transaktion wird als nicht festgeschriebene Transaktion behandelt. Eine nicht komprimierbare Transaktion führt nur eine ROLLBACK TRANSACTION oder einen Lesevorgang aus.
Transaction führt keine Transact-SQL-Anweisungen aus, die Transaktionscommits oder Schreibvorgänge ausführen.
@@ERROR
Die Funktion @@ERROR gibt die Fehlernummer der zuletzt ausgeführten T-SQL-Anweisung zurück.
Syntax:
@@ERROR
Zum Beispiel:
USE AdventureWorks2019; GO BEGIN TRY UPDATE HumanResources.EmployeePayHistory SET PayFrequency = 4 WHERE BusinessEntityID = 1; END TRY BEGIN CATCH IF @@ERROR = 547 PRINT N'Check constraint violation has occurred.'; END CATCH
RAISERROR
Die RAISERROR-Anweisung leitet die Fehlerbehandlung für eine Sitzung ein und zeigt die Fehlermeldung an.
RAISERROR kann auf benutzerdefinierte Nachrichten verweisen, die in der Katalogansicht sys.message gespeichert sind, oder zur Laufzeit eine dynamische Fehlermeldung erstellen.
Syntax:
RAISERROR ( {msg_id | msg_str | @local_variable} {,serverity , state} [,argument,[,...n]]) [WITH option [,...n]]
Da drin:
- msg_id : Gibt benutzerdefinierte Fehlermeldungen an, die in der Katalogansicht sys.messages mit sp_addmessage gespeichert werden.
- msg_str : definiert benutzerdefinierte Fehlermeldungen mit Formatierung. msg_str ist eine Zeichenfolge mit Konvertierungsoptionen. Parameter können d,i,o,s,x,X,u sein, ähnlich dem String-Format in der printf-Funktion.
Werteliste für benutzerdefinierte Optionen:
Wert | Bezeichnung |
PROTOKOLL | Fehler in Datenbank- und Anwendungsfehlerprotokollen protokollieren. |
JETZT WARTEN | Senden Sie Benachrichtigungen direkt an den Client |
SETERROR | Weisen Sie msg_id oder 5000 unabhängig vom Schweregrad den Wert ERROR_NUMBER und @@ERROR zu |
Die folgenden Fehler werden zurückgegeben, wenn RAISERROR ausgeführt wird:
- Außerhalb des Geltungsbereichs des TRY-Blocks
- Hat einen Schweregrad von 10 oder weniger im TRY-Block
- Schweregrad 20 oder höher, Datenbanktrennung.
Beispiel für die Verwendung von RAISERROR() zum Ausdrucken eines benutzerdefinierten Fehlers:
RAISERROR (N'This is an error message %s %d',10,1,N'serial number',23); GO
Beispiel für die Verwendung von RAISERROR in TRY CATCH:
BEGIN TRY RAISERROR('Raises Error in the TRY block',16,1); END TRY BEGIN CATCH DECLARE @ErrorMessage NVARCHAR(4000); DECLARE @ErrorSeverity INT; DECLARE @ErrorState INT; SELECT @ErrorMessage = ERROR_MESSAGE() , @ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE(); RAISERROR(@ErrorMessage,@ErrorSeverity,@ErrorState); END CATCH;
ERROR_SEVERITY
Die ERROR_SEVERITY-Funktion gibt den Schweregrad des Fehlers im Catch-Block der TRY CATCH-Struktur zurück.
Diese Funktion gibt null zurück, wenn sie außerhalb des CATCH-Blocks aufgerufen wird. ERROR _SEVERITY kann überall im Geltungsbereich des CATCH-Blocks aufgerufen werden.
In einem verschachtelten CATCH-Block gibt ERROR_SEVERITY einen Fehler zurück, der den Geltungsbereich des Catch-Blocks bestimmt, auf den er sich bezieht.
Syntax:
ERROR_SEVERITY()
Zum Beispiel:
BEGIN TRY SELECT 217/0; END TRY BEGIN CATCH SELECT ERROR_SEVERITY() AS ErrorSeverity; END CATCH; GO
ERROR_PROCEDURE
Die ERROR_PROCEDURE-Funktion gibt den Namen des Triggers oder der gespeicherten Prozedur zurück, wo der Fehler eines TRY CATCH-Konstrukts ausgeführt wurde.
Syntax:
ERROR_PROCEDURE()
Es gibt den Datentyp nvarchar zurück. Wenn die Funktion im CATCH-Block aufgerufen wird, gibt sie den Namen der gespeicherten Prozedur zurück, in der der Fehler aufgetreten ist.
ERROR_PROCEDURE kann überall innerhalb des CATCH-Blocks aufgerufen werden.
Zum Beispiel:
USE AdventureWorks2019; GO IF OBJECT_ID ('usp_Example','P') IS NOT NULL DROP PROCEDURE usp_Example; GO CREATE PROCEDURE usp_Example AS SELECT 217/0; GO BEGIN TRY EXECUTE usp_Example; END TRY BEGIN CATCH SELECT ERROR_PROCEDURE() AS ErrorProcedure; END CATCH; GO
FEHLERNUMMER
Die im CATCH-Block aufgerufene ERROR_NUMBER-Funktion gibt die Anzahl der vom CATCH-Block generierten Fehler zurück, wenn die TRY >> CATCH-Struktur ausgeführt wird.
Syntax:
ERROR_NUMBER()
ERROR_NUMBER gibt unabhängig von der Anzahl der Fehlerausführungen (bei mehreren Ausnahmen in verschiedenen Anweisungen) den entsprechenden Fehlercode zurück und wird im Rahmen des CATCH-Blocks ausgeführt. Dies unterscheidet sich von @@ERROR, da es die interne Fehlernummer nur unmittelbar bei einem Fehler zurückgibt und der Bereich nur auf der ersten Anweisung im CATCH-Block liegt.
Zum Beispiel:
BEGIN TRY SELECT 217/0; SELECT 218/0; END TRY BEGIN CATCH SELECT ERROR_NUMBER() AS ErrorNumber; END CATCH; GO
FEHLERMELDUNG
Die ERROR_MESSAGE-Funktion gibt die Textnachricht des in der Struktur verursachten Fehlers in der TRY CATCH-Struktur zurück.
Syntax:
ERROR_LINE()
Wenn diese Funktion in einem CATCH-Block aufgerufen wird, gibt sie den vollständigen Text der Fehlermeldung zurück, die zur Ausführung des CATCH-Blocks geführt hat.
Der Text enthält die Werte, die für alle Parameter bereitgestellt werden, die ersetzt werden können, z. B. Objektname, Zeit oder Länge.
Zum Beispiel:
BEGIN TRY SELECT 200/0; END TRY BEGIN CATCH SELECT ERROR_MESSAGE() AS ErrorMessage; END CATCH; GO
ERROR_LINE
Die ERROR_LINE-Funktion gibt die Anzahl der Zeilen mit Fehlern im TRY CATCH-Block zurück.
Syntax:
ERROR_LINE()
Wenn die Funktion im CATCH-Block aufgerufen wird, gibt sie die Anzahl der Zeilen zurück, in denen der Fehler aufgetreten ist. Wenn innerhalb eines Triggers oder einer gespeicherten Prozedur ein Fehler auftritt, wird die Anzahl der Zeilen in diesem Trigger oder dieser gespeicherten Prozedur zurückgegeben. Ähnlich wie andere Funktionen gibt diese Funktion NULL zurück, wenn sie außerhalb des Geltungsbereichs des CATCH-Blocks aufgerufen wird.
Zum Beispiel:
BEGIN TRY SELECT 217/0; END TRY BEGIN CATCH SELECT ERROR_LINE() AS ErrorLine; END CATCH; GO
Fehler, die nicht vom TRY CATCH-Konstrukt betroffen sind
Der TRY CATCH-Block fängt die folgenden Bedingungen nicht ab:
- Die Informationen der Nachricht oder Warnung haben einen Schweregrad von 10 oder weniger.
- Ein Fehler mit Schweregrad 20 oder höher stoppt die SQL Server-Datenbankmodul-Ausführungstask für die Sitzung.
- Wenn der aufgetretene Fehler einen Schweregrad von 20 oder höher hat und die Datenbankverbindung nicht unterbrochen wird, behandelt TRY CATCH den Fehler.
- Beachten Sie z. B. eine unterbrochene Client-Verbindung oder unterbrochene Anforderungen.
- Wenn die Sitzung mit der KILL-Anweisung über den Systemadministrator beendet wird.
Die folgenden Fehlertypen, die nicht von einem CATCH-Block behandelt werden, treten auf derselben Ausführungsebene wie die des TRY CATCH-Konstrukts auf:
- Kompilierungsfehler als Rechtsfehler.
- Fehler, die während der Kompilierung auf Anweisungsebene auftreten, z. B. Fehler bei der Objektnamenauflösung (Objektname existiert nicht), treten nach der Kompilierung aufgrund einer verzögerten Namensauflösung auf.
Zum Beispiel:
USE AdventureWorks2109; GO BEGIN TRY SELECT * FROM Nonexistent; END TRY BEGIN CATCH SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage; END CATCH
WURF
Die THROW-Anweisung löst eine Ausnahme aus und überträgt die Steuerung der Ausführung an einen CATCH-Block einer TRY…CATCH-Struktur.
Syntax:
THROW [{error_number | @local_varibale}, {message | @local_variable}, {state | @local_variable}] [;]
Zum Beispiel:
USE tempdb; GO CREATE TABLE dbo.TestRethrow (ID INT PRIMARY KEY); BEGIN TRY INSERT dbo.TestRethrow(ID) VALUES(1); INSERT dbo.TestRethrow(ID) VALUES(1); END TRY BEGIN CATCH PRINT 'In catch block.'; THROW END CATCH;
Wenn THROW verwendet wird, wird die PRINT-Anweisung innerhalb des CATCH-Blocks weiterhin gedruckt, obwohl der Befehl nicht gebunden werden kann, was die Rolle von THROW in SQL Server ist.