Поделиться через


Получение сведений об ошибках в языке Transact-SQL

Существует два способа получения сведений об ошибках в языке Transact-SQL.

  • В области блока CATCH конструкции TRY…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 возвращают сведения об ошибках только при использовании в области блока CATCH конструкции TRY…CATCH. Вне области блока CATCH они возвращают значение NULL. Эти функции возвращают сведения об ошибке, приведшей к активированию блока CATCH. Данные функции возвращают одни и те же сведения об ошибке при выполнении в любой точке области блока CATCH, даже если на эти функции имеется несколько ссылок. Функции предоставляют инструкциям языка Transact-SQL те же данные, которые возвращаются приложению.

Во вложенных блоках CATCH функции ERROR_LINE, ERROR_MESSAGE, ERROR_NUMBER, ERROR_PROCEDURE, ERROR_SEVERITY и ERROR_STATE возвращают сведения об ошибках, специфичных для блока CATCH, в котором содержатся ссылки на эти функции. Например, блок CATCH внешней конструкции TRY...CATCH может содержать вложенную конструкцию TRY...CATCH. Внутри вложенного блока CATCH эти функции возвращают сведения об ошибке, активировавшей внутренний блок CATCH. Те же функции во внешнем блоке CATCH возвращают данные об ошибке, активировавшей этот блок CATCH.

Следующий пример иллюстрирует эту мысль. Из него явствует, что когда ссылка на функцию ERROR_MESSAGE содержится во внешнем блоке CATCH, она возвращает текст сообщения, сформированного внешним блоком TRY. Если же ссылка на функцию ERROR_MESSAGE содержится во внутреннем блоке CATCH, она возвращает текст сообщения, сформированного внутренним блоком 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, значение @@ERROR должно быть проверено и считано первой инструкцией в ассоциированном блоке CATCH.

  • Если создающая ошибку инструкция находится вне блока 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