我有一个包含国家、城市、位置、描述列的表。由于描述字段的大小,无法将四个字段绑定到复合键中以防止重复。我一直试图通过触发器来防止重复,但无论我尝试什么,它都会回滚每个插入,包括唯一数据的插入。
IF Exists ( Select a.*
From [dbo].[Table] a
JOIN Inserted b
on a.Country = b.Country
and a.City = b.City
and a.Location = b.Location
and ltrim(rtrim(a.Description)) = ltrim(rtrim(b.Description))
)
BEGIN
Raiserror ('The description that you are trying to load already exists.', 16, 1)
Rollback
END
有没有人知道上面有什么问题,我需要做哪些改变才能让它只回滚重复的插入?
我认为您正在检查的条件将始终为真,因为对于执行的每个插入查询都会有一个条目,
dbo.Table
因此inserted
它也会回滚事务。来自 MSDN
我建议您在插入之前检查重复项
更多阅读:http: //msdn.microsoft.com/en-in/library/ms191300.aspx
我怀疑您正在使用
AFTER INSERT
触发器(如果您没有指定其他触发器的AFTER
类型,请为我们提供触发器定义的完整代码以供我们确定)所以这是预期的:您的触发器在插入后触发,因此它将始终查看您刚刚放入的行。而不是
IF EXISTS ...
你可以做IF (SELECT COUNT(*) ...) > 1
which 将检查你的新行是否使总数超过一。您也可以使用一个
INSTEAD OF INSERT
触发器,它可能会更有效一些(做更少的工作,您以后会回滚),但我怀疑差异是否会很大,除非您在该表上有一个非常插入大量的工作负载并且有很多重复项。两个要点:
首先确保您也处理过
UPDATES
,否则您也可以通过这种方式获得重复项。其次,确保您所做的事情实际上是值得的:试图在自由文本输入字段(如“描述”)上强制执行数据完整性通常是一个失败的原因。您可能有两个相同的条目,除了一个有两个空格或拼写错误,并且您的检查不会将它们视为等同的。