Verwenden von @@ERROR

Die @@ERROR-Systemfunktion gibt 0 zurück, wenn die letzte Transact-SQL-Anweisung erfolgreich ausgeführt wurde; falls die Anweisung einen Fehler generiert hat, gibt @@ERROR die Fehlernummer zurück. Der Wert von @@ERROR ändert sich nach Abschluss jeder einzelnen Transact-SQL-Anweisung.

Da @@ERROR jedes Mal einen neuen Wert erhält, wenn eine Transact-SQL-Anweisung abgeschlossen wird, stehen zur Verarbeitung von @@ERROR zwei Möglichkeiten zur Verfügung:

  • Sofortiges Testen oder Verwenden von @@ERROR nach der Transact-SQL-Anweisung.

  • Sofortiges Speichern von @@ERROR in einer ganzzahligen Variablen, nachdem die Transact-SQL-Anweisung abgeschlossen ist. Der Wert der Variablen kann später verwendet werden.

Wenn sich die Anweisung, die den Fehler generiert, nicht im TRY-Block eines TRY…CATCH-Konstrukts befindet, muss @@ERROR getestet oder in der Anweisung sofort nach der Anweisung verwendet werden, die den Fehler generiert hat. Wenn sich die Anweisung, die den Fehler generiert, in einem TRY-Block befindet, kann @@ERROR getestet oder in der ersten Anweisung im zugehörigen CATCH-Block verwendet werden. Im Bereich eines CATCH-Blockes kann die ERROR_NUMBER-Funktion zum Abrufen der gleichen Fehlernummer verwendet werden, die durch @@ERROR protokolliert wird. ERROR_NUMBER besitzt den Vorteil, dass diese Funktion für alle Anweisungen im Bereich des CATCH-Blockes verfügbar ist, während @@ERROR durch die erste Anweisung im CATCH-Block zurückgesetzt wird.

Bedingte Anweisungen, z. B. die IF-Anweisung, setzen @@ERROR zurück. Wenn Sie auf @@ERROR in einer IF-Anweisung verweisen, rufen Verweise auf @@ERROR in IF- oder ELSE-Blöcken nicht die @@ERROR-Informationen ab. Im folgenden Beispiel wird @@ERROR durch IF zurückgesetzt und gibt nicht die Fehlernummer zurück, wenn ein Verweis auf die Funktion in der PRINT-Anweisung erfolgt.

DECLARE @ErrorVar INT

RAISERROR(N'Message', 16, 1);
IF @@ERROR <> 0
    -- This PRINT statement prints 'Error = 0' because
    -- @@ERROR is reset in the IF statement above.
    PRINT N'Error = ' + CAST(@@ERROR AS NVARCHAR(8));
GO

Das folgende Beispiel gibt die erwarteten Ergebnisse zurück:

DECLARE @ErrorVar INT

RAISERROR(N'Message', 16, 1);
-- Save the error number before @@ERROR is reset by
-- the IF statement.
SET @ErrorVar = @@ERROR
IF @ErrorVar <> 0
-- This PRINT statement correctly prints 'Error = 50000'.
    PRINT N'Error = ' + CAST(@ErrorVar AS NVARCHAR(8));
GO

Wenn Sie auf @@ERROR und @@ROWCOUNT verweisen möchten, nachdem eine Anweisung ausgeführt wurde, muss auf beide Funktionen in der gleichen Anweisung verwiesen werden. @@ERROR und @@ROWCOUNT werden durch jede Transact-SQL-Anweisung zurückgesetzt; auf beide Funktionen muss daher in der gleichen Anweisung unmittelbar nach der getesteten Anweisung verwiesen werden. Im folgenden Beispiel ist @@ROWCOUNT immer 0, weil auf die Funktion erst verwiesen wird, nachdem sie durch die erste PRINT-Anweisung zurückgesetzt wurde.

USE AdventureWorks2008R2;
GO
DELETE FROM HumanResources.JobCandidate
    WHERE JobCandidateID = 13;
-- This PRINT would successfully capture any error number.
PRINT N'Error = ' + CAST(@@ERROR AS NVARCHAR(8));
-- This PRINT will always print 'Rows Deleted = 0 because
-- the previous PRINT statement set @@ROWCOUNT to 0.
PRINT N'Rows Deleted = ' + CAST(@@ROWCOUNT AS NVARCHAR(8));
GO

Das folgende Beispiel gibt die erwarteten Ergebnisse zurück:

USE AdventureWorks2008R2;
GO
DECLARE @ErrorVar INT;
DECLARE @RowCountVar INT;

DELETE FROM HumanResources.JobCandidate
  WHERE JobCandidateID = 13;
-- Save @@ERROR and @@ROWCOUNT while they are both
-- still valid.
SELECT @ErrorVar = @@ERROR,
    @RowCountVar = @@ROWCOUNT;
IF (@ErrorVar <> 0)
    PRINT N'Error = ' + CAST(@ErrorVar AS NVARCHAR(8));
PRINT N'Rows Deleted = ' + CAST(@RowCountVar AS NVARCHAR(8));
GO

@@ERROR wird ausschließlich für Fehler, jedoch nicht für Warnungen ausgelöst; Batches, gespeicherte Prozeduren und Trigger können @@ERROR nicht zum Erkennen von Warnungen verwenden, die aufgetreten sind.

@@ERROR wird in SQL Server 2000 und früheren Versionen häufig verwendet, um den Erfolg oder das Fehlschlagen einer gespeicherten Prozedur anzugeben. Eine ganzzahlige Variable wird mit 0 initialisiert. Nach dem Abschluss jeder Transact-SQL-Anweisung wird getestet, ob @@ERROR den Wert 0 besitzt. Wenn dies nicht der Fall ist, wird der Wert in der Variablen gespeichert. Die Prozedur gibt die Variable dann für die RETURN-Anweisung zurück. Wenn bei keiner der Transact-SQL-Anweisungen in der Prozedur ein Fehler aufgetreten ist, bleibt der Wert der Variablen 0. Generiert mindestens eine Anweisung einen Fehler, enthält die Variable die letzte Fehlernummer. Das folgende Beispiel zeigt eine einfache gespeicherte Prozedur mit dieser Logik:

USE AdventureWorks2008R2;
GO
IF EXISTS(SELECT name FROM sys.objects
          WHERE name = N'SampleProcedure')
    DROP PROCEDURE SampleProcedure;
GO
-- Create a procedure that takes one input parameter
-- and returns one output parameter and a return code.
CREATE PROCEDURE SampleProcedure @EmployeeIDParm INT,
    @MaxVacation INT OUTPUT
AS

    -- Declare and initialize a variable to hold @@ERROR.
    DECLARE @ErrorSave1 INT, @ErrorSave2 INT;
    SET @ErrorSave1 = 0;

    -- Do a SELECT using the input parameter.
    SELECT LoginID, NationalIDNumber, JobTitle
        FROM HumanResources.Employee
        WHERE BusinessEntityID = @EmployeeIDParm;

    -- Save @@ERROR value in first local variable.
    SET @ErrorSave1 = @@ERROR;

    -- Set a value in the output parameter.
    SELECT @MaxVacation = MAX(VacationHours)
        FROM HumanResources.Employee;

    -- Save @@ERROR value in second local variable. 
    SET @ErrorSave2 = @@ERROR;
    -- If second test variable contains non-zero value, 
    -- overwrite value in first local variable.
    IF (@ErrorSave2 <> 0) SET @ErrorSave1 = @ErrorSave2;

    -- Returns 0 if neither SELECT statement had
    -- an error; otherwise, returns the last error.
    RETURN @ErrorSave1;
GO
    
DECLARE @OutputParm INT;
DECLARE @ReturnCode INT;

EXEC @ReturnCode = SampleProcedure 13, @OutputParm OUTPUT;

PRINT N'OutputParm = ' + CAST(@OutputParm AS NVARCHAR(20));
PRINT N'ReturnCode = ' + CAST(@ReturnCode AS NVARCHAR(20));
GO

Wenn @@ERROR als primäres Mittel zum Erkennen von Fehlern verwendet wird, ergibt sich ein vollkommen anderer Stil für den Fehlerbehandlungscode als bei TRY…CATCH-Konstrukten.

  • @@ERROR muss entweder getestet oder nach jeder Transact-SQL-Anweisung gespeichert werden, weil ein Entwickler nicht vorhersagen kann, welche Anweisung möglicherweise einen Fehler generiert. Auf diese Weise wird die Anzahl der Transact-SQL-Anweisungen verdoppelt, die für die Implementierung eines bestimmten Teils einer Programmlogik codiert werden müssen.

  • TRY…CATCH-Konstrukte sind wesentlich einfacher. Ein Block von Transact-SQL-Anweisungen wird durch BEGIN TRY- und END TRY-Anweisungen gebunden, anschließend wird ein CATCH-Block geschrieben, um Fehler zu behandeln, die möglicherweise von diesem Anweisungsblock generiert werden können.

@@ERROR ist außerhalb eines CATCH-Blockes der einzige Teil eines Database Engine (Datenbankmodul)-Fehlers, der innerhalb des Batches, der gespeicherten Prozedur oder des Triggers zur Verfügung steht, der den Fehler generiert hat. Alle anderen Teile des Fehlers, wie z. B. Schweregrad, Status und Meldungstext mit Ersetzungszeichenfolgen (z. B. Objektnamen), werden nur an die Anwendung zurückgegeben, in der sie dann mithilfe der API-Fehlerbehandlungsmechanismen verarbeitet werden können. Wenn der Fehler einen CATCH-Block aufruft, können die Systemfunktionen ERROR_LINE, ERROR_MESSAGE, ERROR_PROCEDURE, ERROR_NUMBER, ERROR_SEVERITY und ERROR_STATE verwendet werden.

Community-Beiträge

HINZUFÜGEN
Anzeigen: