【问题标题】:Why custom exception using Throw doesn't execute next statement, whereas table constraint exception does it为什么使用 Throw 的自定义异常不执行下一条语句,而表约束异常却执行
【发布时间】:2014-12-04 18:03:37
【问题描述】:

我有一个带有 Id smallint 和 Code varchar(5) 字段的表,代码上有一个唯一键约束。 表中的代码字段中已经有一行带有“ABC”的行

我已经编写了以下存储过程来向其中插入值

            ALTER Procedure [dbo].[Insert]
                @Id smallint output,
                @Code varchar(5)
            AS
            SET NOCOUNT OFF;
            IF not EXISTS (select Code from SomeTable where Code like '%'+@Code and Code <> @Code)
            BEGIN
                Insert into dbo.SomeTable (Code) values (@Code)
            END
            ELSE
            BEGIN
               Throw 50000,'Violation of UNIQUE KEY constraint. Cannot insert Code which is already a suffix of existing Code in table ''dbo.SomeTable''.',1
            END
            Select Id,Code from dbo.SomeTable  where SomeTableCode = 'ABC'

您可以看到我已经编写了自定义抛出异常,当代码作为任何现有代码的后缀出现时应该抛出这个异常。

当我使用以下语句测试插入重复代码时

    DECLARE @return_value int,
            @Id smallint

    EXEC    @return_value = [dbo].[Insert]
            @Id = @Id OUTPUT,
            @Code = N'ABC'

我得到以下异常:

    Msg 2627, Level 14, State 1, Procedure Insert, Line 19
    Violation of UNIQUE KEY constraint 'IX_SomeTable_1'. Cannot insert duplicate key in object 'dbo.SomeTable'. The duplicate key value is (ABC).
    The statement has been terminated.
    (1 row(s) affected)

我可以看到结果选项卡中的行(执行了选择语句)

但是当我尝试使用以下语句将代码作为后缀插入表中的另一个代码时:

    DECLARE @return_value int,
            @Id smallint

    EXEC    @return_value = [dbo].[Insert]
            @Id = @Id OUTPUT,
            @Code = N'BC'

我收到以下错误,但未执行 Select 语句,我在结果选项卡中看不到行,为什么?

    Msg 50000, Level 16, State 1, Procedure Insert, Line 24
    Violation of UNIQUE KEY constraint. Cannot insert Code which is already a suffix of existing Code in table 'dbo.SomeTable'.

【问题讨论】:

    标签: sql-server-2012


    【解决方案1】:

    根据THROW on MSDN

    如果 TRY…CATCH 构造不可用,则会话结束

    您没有使用 TRY/CATCH,因此 THROW 会停止存储过程的执行。

    一般来说,这种支付方式是不可靠的

    • 两个并发会话都可以找到NOT EXISTS 为真,但只有一个插入可以成功。使用 MERGE
    • THROW 显示“已存在或作为后缀存在”,实际上并非违规
    • 没有尝试/捕获

    编辑,使用类似的东西

    BEGIN TRY
        MERGE into dbo.SomeTable
        etc
    
    END TRY
    BEGIN CATCH
        DECLARE @errmsg nvarchar(2000);
        IF ERROR_NUMBER() = 2627
            SET @errmsg = 'Already exists etc'
        ELSE
            SET @errmsg = ERROR_MESSAGE();
        THROW 50000, @errmsg, 1;
    END CATCH
    SELECT Id,Code from dbo.SomeTable  where SomeTableCode = 'ABC';
    

    并完整阅读Error Handling in SQL 2005 and Later

    【讨论】:

    • 我可以进行哪些更改来引发异常以及执行下一条语句?
    猜你喜欢
    • 1970-01-01
    • 2018-07-07
    • 1970-01-01
    • 2019-06-06
    • 1970-01-01
    • 2015-02-27
    • 1970-01-01
    • 2014-03-24
    • 1970-01-01
    相关资源
    最近更新 更多