从存储过程返回错误消息

Ciu*_*caS 3 sql-server stored-procedures sql-server-2012

这个问题应该很简单,但我无法弄清楚答案,也不知道为什么我的存储过程不起作用.

CREATE PROCEDURE spTest_Delete
@ID int
AS
    begin tran
        declare @err int
        declare @errMesage nvarchar(max)
        set @errMesage = ''
        set @err = 0

        delete from Test
        where ID = @ID

        set @err = @@ERROR
        set @errMesage = ERROR_MESSAGE()

        if @err = 0 
           commit tran
        else 
        begin
            RAISERROR(N'Could not delete !Error nr: %d. Message: %s', 1, 16, @err, @errMesage)
            rollback tran
        end
Run Code Online (Sandbox Code Playgroud)

这个过程运行正常,但是如果对delete语句有FK约束,它会遇到错误(这很好),我想抓住错误.

消息547,级别16,状态0,过程spTest_Delete,第12行
DELETE语句与REFERENCE约束"FK_TEstFK_Test"冲突.冲突发生在数据库"Test",表"dbo.Test",列"ID"中.该语句已终止.

无法删除!
错误号:547.消息:(null)消息50000,级别1,状态16

我的消息变量总是为null,即使该delete语句引发错误.

Rah*_*thi 10

尝试使用 TRY CATCH 并捕获您的错误,如下所示:

BEGIN TRY
   delete from Test
    where  ID = @ID
END TRY
BEGIN CATCH
    SET @ErrorMessage  = ERROR_MESSAGE()
    SET @ErrorSeverity = ERROR_SEVERITY()
    SET @ErrorState    = ERROR_STATE()
    RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState)
    BREAK
END CATCH
Run Code Online (Sandbox Code Playgroud)

  • .net端如何捕获ErrorMessage? (3认同)

Eva*_*kas 6

您可能希望在过程中开始使用TRY..CATCH

实现Transact-SQL的错误处理,类似于Microsoft Visual C#和Microsoft Visual C++语言中的异常处理.一组Transact-SQL语句可以包含在TRY块中.如果TRY块中发生错误,则将控制权传递给包含在CATCH块中的另一组语句.

所以你的程序可以改写为:

CREATE PROCEDURE spTest_Delete @ID INT
AS
BEGIN
    SET NOCOUNT ON;
    BEGIN TRY
        BEGIN TRANSACTION
            DELETE
            FROM Test
            WHERE ID = @ID;
        COMMIT TRANSACTION
    END TRY
    BEGIN CATCH
        IF @@TRANCOUNT > 0
            ROLLBACK TRANSACTION
        SELECT ERROR_NUMBER(), ERROR_MESSAGE();
    END CATCH
END
Run Code Online (Sandbox Code Playgroud)

此外,请注意您作为单个删除语句运行.这意味着它不需要包含在事务中.这个问题解释了原因.

你的代码变成了这样:

CREATE PROCEDURE spTest_Delete @ID INT
AS
BEGIN
    SET NOCOUNT ON;
    BEGIN TRY
        DELETE
        FROM Test
        WHERE ID = @ID;
    END TRY
    BEGIN CATCH
        SELECT ERROR_NUMBER(), ERROR_MESSAGE();
    END CATCH
END
Run Code Online (Sandbox Code Playgroud)

为什么你@errMessage的总是NULL?因为ERROR_MESSAGE()仅在CATCH块中有效.这是用文档写的:

返回导致运行TRY ... CATCH构造的CATCH块的错误的消息文本.

在Transact-SQL中使用TRY..CATCH告诉:

通过在TRY ... CATCH构造的CATCH块范围内的任何位置使用这些函数来检索错误信息.如果在CATCH块的范围之外调用,则错误函数将返回NULL.