使用 @@ERROR
在 SQL Server 2000 和更舊的版本中,@@ERROR 函數是偵測 Transact-SQL 陳述式中錯誤的主要方式。SQL Server 2005 Database Engine 推出 TRY…CATCH 建構,提供了功能的改善。如需詳細資訊,請參閱<在 Transact-SQL 中使用 TRY...CATCH>。@@ERROR 也會傳回前一個陳述式所發生的錯誤數目。SQL Server 2005 推出提供更多錯誤資訊的其他功能。如需詳細資訊,請參閱<在 Transact-SQL 中擷取錯誤資訊>。
如果上一個 Transact-SQL 陳述式執行成功,@@ERROR 系統函數會傳回 0;如果陳述式產生錯誤,則 @@ERROR 會傳回錯誤號碼。每個 Transact-SQL 陳述式完成後,@@ERROR 的值就會改變。
因為 @@ERROR 會在每個 Transact-SQL 陳述式完成後取得新值,您可使用以下兩種方法之一來處理 @@ERROR:
- Transact-SQL 陳述式完畢後立即測試或使用 @@ERROR。
- 在 Transact-SQL 陳述式完成後立即以整數變數儲存 @@ERROR。這個變數值可以供之後使用。
如果陳述式產生的錯誤不是在 TRY…CATCH 建構的 TRY 區塊中,在陳述式產生錯誤後,就必須立即在陳述式中測試或使用 @@ERROR。如果陳述式產生的錯誤是在 TRY 區塊中,可以在關聯的 CATCH 區塊的第一個陳述式中測試或使用 @@ERROR。在 CATCH 區塊的範圍中,ERROR_NUMBER 函數可用以擷取 @@ERROR 所報告的相同錯誤號碼。ERROR_NUMBER 的優點在於,它可供 CATCH 區塊範圍中的所有陳述式使用,然而 @@ERROR 是由 CATCH 區塊中的第一個陳述式所重設。
條件式陳述式 (例如 IF 陳述式) 會重設 @@ERROR。如果在 IF 陳述式中參考 @@ERROR,參考 IF 或 ELSE 區塊中的 @@ERROR 將不會擷取 @@ERROR 資訊。在下列範例中,IF 重設了 @@ERROR,而且在 PRINT 陳述式中參考時,不會傳回錯誤號碼。
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
下列範例會傳回預期的結果。
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
如果您想要在執行陳述式後參考 @@ERROR 與 @@ROWCOUNT,就必須在相同的陳述式中參考它們。@@ERROR 與 @@ROWCOUNT 是以每個 Transact-SQL 陳述式來重設;因此,在測試後必須立即在相同的陳述式中同時參考它們兩個。在下列範例中,@@ROWCOUNT 永遠都是 0,因為在重設第一個 PRINT 陳述式後,才會參考它。
USE AdventureWorks;
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
下列範例會傳回預期的結果。
USE AdventureWorks;
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 只會針對錯誤而不會針對警告來引發;所以批次、預存程序和觸發程序無法使用 @@ERROR 來偵測所發生的任何警告。
在 SQL Server 2000 和舊版中,@@ERROR 的一般用途是用以指出預存程序的成功或失敗。整數變數是初始化為 0。在每個 Transact-SQL 陳述式完成後,將會測試 @@ERROR 是否為 0,如果它不是 0,就會儲存在變數中。程序接著會針對 RETURN 陳述式傳回變數。如果程序中的 Transact-SQL 陳述式有錯誤,變數值仍然會是 0。如果有一或多個陳述式產生錯誤,變數會保留上一個錯誤號碼。下列範例顯示使用此邏輯的簡單預存程序。
USE AdventureWorks;
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, Title
FROM HumanResources.Employee
WHERE EmployeeID = @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
@@ERROR 與 TRY...CATCH
使用 @@ERROR 做為偵測錯誤的主要方式,將可促成與使用 TRY…CATCH 建構非常不同風格的錯誤處理程式碼。
- 在每個 Transact-SQL 陳述式後面必須測試或儲存 @@ERROR ,因為開發人員無法事先預測哪些陳述式可能產生錯誤。這將使實作指定邏輯所需撰寫的 Transact-SQL 陳述式之數目加倍。
- TRY…CATCH 建構比較簡單。Transact-SQL 陳述式的區塊是由 BEGIN TRY 與 END TRY 陳述式所限定,並撰寫一個 CATCH 區塊以處理陳述式區塊可能產生的錯誤。
在 CATCH 區塊的外面,@@ERROR 是 Database Engine 錯誤中,唯一適用於產生錯誤的批次、預存程序或觸發程序的部份。此錯誤的所有其他部份,例如嚴重性、狀態和包含替代字串的訊息文字 (例如,物件名稱),僅傳至具備 API 錯誤處理機制的應用程式。如果錯誤叫用 CATCH 區塊,就會使用 ERROR_LINE、ERROR_MESSAGE、ERROR_PROCEDURE、ERROR_NUMBER、ERROR_SEVERITY 以及 ERROR_STATE。
請參閱
概念
使用 RAISERROR
處理應用程式中的錯誤和訊息
在 Transact-SQL 中使用 TRY...CATCH
其他資源
@@ERROR (Transact-SQL)
TRY...CATCH (Transact-SQL)
ERROR_LINE (Transact-SQL)
ERROR_MESSAGE (Transact-SQL)
ERROR_NUMBER (Transact-SQL)
ERROR_PROCEDURE (Transact-SQL)
ERROR_SEVERITY (Transact-SQL)
ERROR_STATE (Transact-SQL)