2014-12-04 67 views
0

我有一个ID为smallint和Code varchar(5)字段的表,在代码上有一个唯一键约束。 已经有一排“ABC”的代码字段表为什么使用Throw自定义异常不执行下一条语句,而表约束异常呢它

我已经写了下面的存储过程中插入值,它

  ALTER Procedure [dbo].[Insert] 
       @Id smallint output, 
       @Code varchar(5) 
      AS 
      SET NOCOUNT OFF; 
      IF not EXISTS (select Code from SomeTable where Code like '%'[email protected] 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) 

而且我可以看到在结果选项卡中的行(select语句执行)

但是,当我尝试使用以下语句将代码作为后缀插入到表中的其他代码中时:

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'. 

回答

0

THROW on MSDN

如果一个try ... catch结构是不可用的,

您未使用的try/catch所以THROW停止存储过程的会话结束执行。

一般来说,这payttern是不可靠的

  • 两个并发会话既可以找到NOT EXISTS为真,但只有一个插件能够成功。使用合并
  • 抛出正显示出“已存在或存在作为后缀”,它实际上不是违反
  • 没有的try/catch

编辑,使用类似

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

+0

我可以做出什么改变来抛出异常以及执行下一条语句? – 2014-12-04 09:56:00

相关问题