使用触发器SQL防止重复
我的目标是插入第一个插入,但不要让第二个通过,因为NIC是重复的。我不知道为什么,但它不会让第一个通过而没有其他NIC进行比较,如果它已经存在一个相等的 我知道我可以使用“唯一”来防止重复,但我尝试使用触发器:/使用触发器SQL防止重复,sql,sql-server,tsql,Sql,Sql Server,Tsql,我的目标是插入第一个插入,但不要让第二个通过,因为NIC是重复的。我不知道为什么,但它不会让第一个通过而没有其他NIC进行比较,如果它已经存在一个相等的 我知道我可以使用“唯一”来防止重复,但我尝试使用触发器:/ Create table Utentes ( numUtente nchar(3), Name nchar(40) not null, NIC nchar(8) not null, Constraint PK_Utente Primary Key(num
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已在数据库中Msg 3609,第16级,状态1,第1392行
事务在触发器中结束。批处理已中止
您应该真正使用约束。“插入后”触发器实际上会将第二行放入表中。希望没有人使用
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;
使用而不是
触发器,如果表中已有新行,则不会向表中添加新行:
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;
您应该真正使用约束。“插入后”触发器实际上会将第二行放入表中。希望没有人使用
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;
使用而不是
触发器,如果表中已有新行,则不会向表中添加新行:
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;
我支持反对使用触发器的观点,并建议使用独特的约束。依我的拙见,我宁愿在ETL层中寻找解决方案,在插入记录时对其进行分组。使用触发器,您将遇到上述并发性和一致性问题,如果表变得足够大,需要花费一些时间来处理,则可能会导致tempdb或T-log膨胀。。依我的拙见,我宁愿在ETL层中寻找解决方案,在插入记录时对其进行分组。使用触发器,您将遇到上述并发性和一致性问题,如果表变得足够大,需要花费一些时间来处理,则可能会导致tempdb或T-log膨胀。
inserted
是一个集合,不一定只是一条记录。因此,您的选择@NIC=NIC from inserted
可能会失败或行为与您想象的不同。为什么要拒绝第一个?这是第一张放进去的唱片,所以肯定没有复制品。我想成为第一张被接受的唱片,因为没有其他唱片。但它甚至不会让第一个触发。你的触发器是后插入触发器。因此,当它到达触发器中的代码时,您应该认为触发触发器的行已经插入到表中。inserted
是一个集合,不一定只是一条记录。因此,您的选择@NIC=NIC from inserted
可能会失败或行为与您想象的不同。为什么要拒绝第一个?这是第一张放进去的唱片,所以肯定没有复制品。我想成为第一张被接受的唱片,因为没有其他唱片。但它甚至不会让第一个触发。你的触发器是后插入触发器。因此,当它到达触发器中的代码时,应该预期导致触发器触发的行已经插入到表中。