使用触发器SQL防止重复

时间:2019-01-18 23:19:53

标签: sql sql-server tsql

我的目标是插入第一个插入物,但不让第二个插入物通过,因为NIC是重复的。我不知道为什么,但是它不允许第一个通过而不让其他NIC比较是否已经存在一个相等的

我知道我可以使用“ unique”防止重复,但是我试图使用触发器:/

Create table Utentes
(
    numUtente nchar(3),
    Name nchar(40) not null,
    NIC nchar(8) not null,
    Constraint PK_Utente Primary Key(numUtente)
)


create trigger tr_Duplicate 
on Utentes 
after insert 
as
    declare @NIC nchar(8)

    select @NIC = NIC from inserted

    if exists(select * from Utentes where NIC = @NIC)
    begin
        print 'NIC already in database'
        rollback
    end
go


insert into Utentes (numUtente, Name, NIC) 
values ('123', 'asd', '12345678')

insert into Utentes (numUtente, Name, NIC) 
values ('124', 'asd', '12345678')

select * from Utentes

结果:

  

NIC已在数据库中
  消息3609,第16级,州1,第1392行
  事务在触发器中结束。该批次已中止。

2 个答案:

答案 0 :(得分:2)

您应该真正使用约束。实际上,“插入后”触发器将把第二行放在表中。 。 。希望没有人使用NOLOCK来阅读它。

无论如何,您必须实际计算行数并查找多次出现的情况。会是这样的:

Create trigger tr_Duplicate on Utentes after INSERT as
begin    
    if exists (select 1
               from utentes u join
                    inserted i
                    on u.nic = i.nic
               group by u.nic
               having count(*) > 1
              )
    begin
        print 'NIC already in database';
        rollback;
    end;
end;

使用instead of触发器,如果​​已有行,则不会在表中添加新行:

create trigger tr_Duplicate on Utentes after INSERT as
begin    
    if exists (select 1
               from utentes u join
                    inserted i
                    on u.nic = i.nic
              )
    begin
        print 'NIC already in database';
        rollback;
    end;
    else
    begin
        insert into utentes
            select i.*
            from inserted i;
    end;
end;

答案 1 :(得分:0)

我反对使用触发器,并且建议使用UNIQUE约束。以我的拙见,我宁愿在ETL层中搜索解决方案,对插入的记录进行分组。使用触发器,您将遇到上述并发性和一致性问题,并且如果表足够大以至于需要一些时间来处理,则可能会膨胀您的tempdb或T-log。