在 Transact-SQL 中擷取錯誤資訊
在 Transact-SQL 中取得錯誤資訊的方法有兩種:
- 在 TRY...CATCH 建構的 CATCH 區塊範圍內,您可以使用下列系統函數:
- ERROR_LINE() 會傳回發生錯誤的行號。
- ERROR_MESSAGE() 會傳回要傳給應用程式的訊息文字。文字包括提供給任何可替代參數的值,例如,長度、物件名稱或次數。
- ERROR_NUMBER() 會傳回錯誤號碼。
- ERROR_PROCEDURE() 會傳回發生錯誤之預存程序或觸發程序的名稱。如果預存程序或觸發程序內並未發生錯誤,此函數會傳回 NULL。
- ERROR_SEVERITY() 會傳回嚴重性。
- ERROR_STATE() 會傳回狀態。
- 在執行任何 Transact-SQL 陳述式後,您可以立即使用 @@ERROR 函數來測試是否有錯誤,並擷取錯誤號碼。
使用 ERROR_LINE、ERROR_MESSAGE、ERROR_NUMBER、ERROR_PROCEDURE、ERROR_SEVERITY 與 ERROR_STATE
ERROR_LINE、ERROR_MESSAGE、ERROR_NUMBER、ERROR_PROCEDURE、ERROR_SEVERITY 以及 ERROR_STATE 函數需用於 TRY...CATCH 建構的 CATCH 區塊範圍內,才會傳回錯誤資訊。若用在 CATCH 區塊的範圍外,將會傳回 NULL。這些函數會傳回造成叫用 CATCH 區塊的錯誤詳細資訊。只要是在 CATCH 區塊內的任何位置執行,這些函數都會傳回相同的錯誤資訊,即使多次參考這些函數也是一樣。這些函數提供給 Transact-SQL 陳述式的資料,與傳回給應用程式的資料相同。
若是在巢狀 CATCH 區塊內,ERROR_LINE、ERROR_MESSAGE、ERROR_NUMBER、ERROR_PROCEDURE、ERROR_SEVERITY 以及 ERROR_STATE 函數會針對參考它們的 CATCH 區塊,傳回該區塊的特定錯誤資訊。例如,外部 TRY...CATCH 建構的 CATCH 區塊可能會有巢狀的 TRY...CATCH 建構。在此巢狀 CATCH 區塊內,這些函數會傳回叫用內部 CATCH 區塊之錯誤的詳細資訊。外部 CATCH 區塊中的相同函數,則會傳回叫用了該 CATCH 區塊之錯誤的詳細資訊。
下例將說明此情況:在外部 CATCH 區塊參考 ERROR_MESSAGE 時,它會傳回由外部 TRY 區塊所產生的訊息文字;當內部 CATCH 區塊參考 ERROR_MESSAGE 時,則會傳回由內部 TRY 區塊中所產生的文字。此範例也說明,在外部 CATCH 區塊中,ERROR_MESSAGE 一定是傳回外部 TRY 區塊中所產生的訊息,即使在執行了內部 TRY...CATCH 建構後也是一樣。
IF EXISTS (SELECT message_id FROM sys.messages
WHERE message_id = 50010)
EXECUTE sp_dropmessage 50010;
GO
EXECUTE sp_addmessage @msgnum = 50010,
@severity = 16,
@msgtext = N'Message text is from the %s TRY block.';
GO
BEGIN TRY -- Outer TRY block.
-- Raise an error in the outer TRY block.
RAISERROR (50010, -- Message id.
16, -- Severity,
1, -- State,
N'outer'); -- Indicate TRY block.
END TRY -- Outer TRY block.
BEGIN CATCH -- Outer CATCH block.
-- Print the error message recieved for this
-- CATCH block.
PRINT N'OUTER CATCH1: ' + ERROR_MESSAGE();
BEGIN TRY -- Inner TRY block.
-- Start a nested TRY...CATCH and generate
-- a new error.
RAISERROR (50010, -- Message id.
16, -- Severity,
2, -- State,
N'inner'); -- Indicate TRY block.
END TRY -- Inner TRY block.
BEGIN CATCH -- Inner CATCH block.
-- Print the error message recieved for this
-- CATCH block.
PRINT N'INNER CATCH: ' + ERROR_MESSAGE();
END CATCH; -- Inner CATCH block.
-- Show that ERROR_MESSAGE in the outer CATCH
-- block still returns the message from the
-- error generated in the outer TRY block.
PRINT N'OUTER CATCH2: ' + ERROR_MESSAGE();
END CATCH; -- Outer CATCH block.
GO
使用 @@ERROR 擷取資訊
@@ERROR 函數可以用來擷取前一個 Transact-SQL 陳述式所產生的錯誤號碼。@@ERROR 一定要緊接著放在產生錯誤的 Transact-SQL 陳述式之後,才會傳回錯誤資訊。
- 如果產生錯誤的陳述式是在 TRY 區塊內,則必須在相關聯的 CATCH 區塊的第一個陳述式中,測試和擷取 @@ERROR 的值。
- 如果產生錯誤的陳述式不在 TRY 區塊內,則必須在產生錯誤的該陳述式之後,立即測試和擷取 @@ERROR 的值。
在 CATCH 區塊的範圍之外,關於 Transact-SQL 程式碼內錯誤的唯一可用資訊就是 @@ERROR 中的錯誤號碼。如果錯誤使用了 sys.messages 中定義的錯誤訊息,您可以依本範例中所述,從 sys.messages 擷取已定義的嚴重性及錯誤訊息文字。
IF EXISTS (SELECT message_id FROM sys.messages
WHERE message_id = 50010)
EXECUTE sp_dropmessage 50010;
GO
-- Define a message with text that accepts
-- a substitution string.
EXECUTE sp_addmessage @msgnum = 50010,
@severity = 16,
@msgtext = N'Substitution string = %s.';
GO
DECLARE @ErrorVariable INT;
-- RAISERROR uses a different severity and
-- supplies a substitution argument.
RAISERROR (50010, -- Message id.
15, -- Severity,
1, -- State,
N'ABC'); -- Substitution Value.
-- Save @@ERROR.
SET @ErrorVariable = @@ERROR;
-- The results of this select illustrate that
-- outside a CATCH block only the original
-- information from sys.messages is available to
-- Transact-SQL statements. The actual message
-- string returned to the application is not
-- available to Transact-SQL statements outside
-- of a CATCH block.
SELECT @ErrorVariable AS ErrorID,
text
FROM sys.messages
WHERE message_id = @ErrorVariable;
GO
請參閱
概念
在 Transact-SQL 中使用 TRY...CATCH
使用 RAISERROR
使用 @@ERROR
其他資源
瞭解 Database Engine 錯誤
sys.messages (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)