当它不是时,触发将数据识别为重复数据

时间:2017-07-18 15:52:00

标签: sql-server triggers duplicates inner-join rollback

我在SQL Server中有这个触发器:

CREATE TRIGGER MyTrigger ON [dbo].[practiseduplicates]   
AFTER INSERT
AS
    IF EXISTS (SELECT * 
               FROM [practiseduplicates] t 
               INNER JOIN inserted i ON i.[money] = t.[money] 
                                     AND i.[Name] = t.[Name] 
                                     AND i.[year month] = t.[year month])
    BEGIN
        ROLLBACK
        RAISERROR ('Duplicated Data', 16, 1);
    END

然后我插入这些值(已经在数据表中):

insert into [practiseduplicates]
values ('2017-02', 'buzzlightyear', '10.09')

当我点击执行时,我预计会弹出错误消息...它确实如此,但是当我将值更改为我知道不在数据表中的信息时

e.g。

'2056-12', 'mr potato head', '12345.09'

错误信息仍会弹出,实际上它应该只是将数据插入表中,有人知道为什么会这样吗?

我怀疑它与我的内部联接声明有关,但我不确定。

2 个答案:

答案 0 :(得分:1)

引自你的问题

  

当我点击执行时,我希望弹出错误信息...它做了什么,然而当我将值更改为我知道不在数据表中的信息时

该语句的斜体部分不太准确,因为即使这些值不在表之前,在运行insert之后,它们就在那里。触发器会触发。

简而言之,您正在创建一个 AFTER INSERT 触发器,并检查插入表中的数据是否已经在表中(插入运行后)。当然触发器每次都会触发,因为如果数据在插入的表中,它就在表中(因为它刚刚插入)。

答案 1 :(得分:0)

所以基本上我使用约束来解决这个而不是触发器声明。

ALTER TABLE [dbo].[practiseduplicates]    
ADD CONSTRAINT [constraintforduplicates] UNIQUE NONCLUSTERED
( [column name],
[column name], etc etc
)

这将使用您在约束语句中声明的列作为要比较的数据来停止所有重复项,并标记它们是否重复并且不会将数据插入表中。

请注意,语句中的列本身具有900字节的约束。因此,例如,如果您有varchar(max)列,则约束将不会运行,因为它可以执行的最大值为900字节。在我的脚本中,我放了varchar(800)。