通过外部try catch在内联过程中转发编号错误

时间:2015-05-05 11:26:19

标签: sql-server tsql

我正在尝试验证我的过程值并抛出自定义异常,因为DAL / CRUD层中需要的数字。这也适用于我的示例。我的问题是我不会再次抛出相同的异常只是因为我有一个外部的try catch用于其他用途,btw捕获不期望的异常。有任何想法吗?内部抛出后我试图使用error_message,因为这是包含substitue参数。但我不能再使用消息 AND 我的具体号码了。例如 50101

create procedure dbo.ValidateString (
@Value nvarchar(max) output,
@Column varchar(100)
) 
as
begin
set nocount on;
begin try
    begin tran;

    if @Value is null
    begin
        raiserror (50201, 11, 0, @Column, @Value);
    end

    set @Value = ltrim(rtrim(@Value));

    if datalength(@Value) = 0
    begin
        raiserror (50211, 11, 0, @Column, @Value);
    end

    commit tran;
    return 0;
end try
begin catch
    if @@trancount > 0
    begin
        rollback tran;
    end

    if error_number() = 50201
    begin
        --argument null
        raiserror (50201, 11, 0, @Column, @Value);
        return 1;
    end

    if error_number() = 50211
    begin
        --argument
        raiserror (50211, 11, 0, @Column, @Value);
        return 1;
    end

    declare 
        @errorMessage nvarchar(max) = error_message(),
        @errorSeverity int = error_severity(),
        @errorState int = error_state();
    raiserror (@errorMessage, @errorSeverity, @errorState);
    return 1;
end catch
set nocount off;
end
go
create procedure dbo.InsertData (
@Name varchar(60),
@Active bit = null
)
as
begin
set nocount on;
begin try
    begin tran;

    exec dbo.ValidateString @Name output, 'Name';

    insert into dbo.tblTest (ID, Name, Active)
        values (newid(), @Name, isnull(@Active, 'false'));

    if @@rowcount = 1
    begin
        commit tran;
        return 0;
    end

    rollback tran;
    return 1;
end try
begin catch
    if @@trancount > 0
    begin
        rollback tran;
    end

    if error_number() = 50201
    begin
        --argument null
        raiserror (50201, 11, 0, 'Name', @Name);
        return 1;
    end

    if error_number() = 50211
    begin
        --argument
        raiserror (50311, 11, 0, 'Name', @Name);
        return 1;
    end

    declare 
        @errorMessage nvarchar(max) = error_message(),
        @errorSeverity int = error_severity(),
        @errorState int = error_state();
    raiserror (@errorMessage, @errorSeverity, @errorState);
    return 1;
end catch
set nocount off;
end
go

1 个答案:

答案 0 :(得分:1)

定义自定义错误时,请设置消息文本以使用参数。这样,每次在嵌套的try-catch场景中重新抛出错误时,都可以传递一个新文本。

sp_addmessage @msgnum = 50005,
              @severity = 11,
              @msgtext = N'Message given: <<%30.20s>>'

GO             
CREATE PROCEDURE dbo.sp_inner_ex AS
BEGIN 

    DECLARE @error INT = 50005
    PRINT 'Raising inner'
    RAISERROR (@error, -- Message id.
               11, -- Severity,
               1, -- State,
               N'Inner error message');
END
GO

CREATE PROCEDURE dbo.sp_outer_ex AS
BEGIN 
    BEGIN TRY
        EXEC dbo.sp_inner_ex
    END TRY
    BEGIN CATCH
        DECLARE @error INT = ERROR_NUMBER()
        PRINT 'Raising outer'
        RAISERROR (@error, -- Message id.
                   11, -- Severity,
                   1, -- State,
                   N'Outer error message');
    END CATCH
END
GO
    EXEC dbo.sp_outer_ex
GO
    sp_dropmessage @msgnum = 50005; 
    DROP PROCEDURE dbo.sp_inner_ex
    DROP PROCEDURE dbo.sp_outer_ex
GO

预期产出:

Raising inner
Raising outer
Msg 50005, Level 11, State 1, Procedure sp_outer_ex, Line 42
Message given: <<           Outer error message>>

请记住以下内容:

  

sp_addmessage是邮件的ID。 msg_id是int,默认值为NULL。用户定义的错误消息的msg_id可以是50,001和2,147,483,647之间的整数。 msg_id和语言的组合必须是唯一的;如果指定语言的ID已存在,则返回错误。

您只能抛出自定义错误,而不是系统错误。

  

RAISERROR ...使用sp_addmessage存储在sys.messages目录视图中的用户定义的错误消息编号。用户定义的错误消息的错误号应大于50000.当未指定msg_id时,RAISERROR会引发错误消息,错误号为50000.