我有一张桌子,不知何故,同一个人Person两次上了我的桌子。现在,主键只是一个自动编号,但还有另外两个字段,我想强制它们是唯一的。
Person
例如,这些字段是:
ID Name Active PersonNumber
我只想要 1 条具有唯一 PersonNumber 且 Active = 1 的记录。 (因此这两个字段的组合需要是唯一的)
SQL Server 中现有表的最佳方法是什么我可以做到,所以如果其他人使用与现有值相同的值进行插入,它会失败,所以我不必在我的应用程序代码中担心这一点。
删除重复项后:
ALTER TABLE dbo.yourtablename ADD CONSTRAINT uq_yourtablename UNIQUE(column1, column2);
或者
CREATE UNIQUE INDEX uq_yourtablename ON dbo.yourtablename(column1, column2);
当然,在让 SQL Server 尝试插入行并返回异常(异常代价高昂)之前,通常最好先检查这种违规情况。
不同错误处理技术的性能影响
在进入 TRY/CATCH 之前检查潜在的约束违规
如果要防止异常冒泡到应用程序,而不对应用程序进行更改,可以使用INSTEAD OF触发器:
INSTEAD OF
CREATE TRIGGER dbo.BlockDuplicatesYourTable ON dbo.YourTable INSTEAD OF INSERT AS BEGIN SET NOCOUNT ON; IF NOT EXISTS (SELECT 1 FROM inserted AS i INNER JOIN dbo.YourTable AS t ON i.column1 = t.column1 AND i.column2 = t.column2 ) BEGIN INSERT dbo.YourTable(column1, column2, ...) SELECT column1, column2, ... FROM inserted; END ELSE BEGIN PRINT 'Did nothing.'; END END GO
但是如果你不告诉用户他们没有执行插入,他们会想知道为什么数据不存在并且没有报告异常。
这里的编辑 是一个完全符合您要求的示例,即使使用与您的问题相同的名称,也可以证明这一点。在假设上述想法只处理一列或另一列而不是组合之前,您应该尝试一下......
USE tempdb; GO CREATE TABLE dbo.Person ( ID INT IDENTITY(1,1) PRIMARY KEY, Name NVARCHAR(32), Active BIT, PersonNumber INT ); GO ALTER TABLE dbo.Person ADD CONSTRAINT uq_Person UNIQUE(PersonNumber, Active); GO -- succeeds: INSERT dbo.Person(Name, Active, PersonNumber) VALUES(N'foo', 1, 22); GO -- succeeds: INSERT dbo.Person(Name, Active, PersonNumber) VALUES(N'foo', 0, 22); GO -- fails: INSERT dbo.Person(Name, Active, PersonNumber) VALUES(N'foo', 1, 22); GO
在所有这些之后表中的数据:
ID Name Active PersonNumber ---- ------ ------ ------------ 1 foo 1 22 2 foo 0 22
最后插入的错误消息:
消息 2627,级别 14,状态 1,第 3 行违反 UNIQUE KEY 约束“uq_Person”。无法在对象“dbo.Person”中插入重复键。该语句已终止。
此外,我最近还写了一篇关于以任一顺 序 将唯一约束应用于两列的解决方案的博客: