Transact-SQL のエラー情報の取得

Transact-SQL のエラー情報を取得する方法は 2 つあります。

  • 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 ブロックでは、内側の TRY...CATCH 構造を実行した後でも、常に ERROR_MESSAGE が外側の TRY ブロックで生成されたメッセージを返します。

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 ステートメントで発生したエラーの番号をキャプチャするために使用します。エラーを発生した 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