删除重复项后:
ALTER TABLE dbo.yourtablename
ADD CONSTRAINT uq_yourtablename UNIQUE(column1, column2);
或
CREATE UNIQUE INDEX uq_yourtablename
ON dbo.yourtablename(column1, column2);
当然,在让 SQL Server 尝试插入行并返回异常(异常代价高昂)之前,最好先检查这种违规行为。
如果您想防止异常冒泡到应用程序,而不对应用程序进行更改,您可以使用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
但是如果你不告诉用户他们没有执行插入,他们会想知道为什么数据不存在并且没有报告异常。
EDIT 这里是一个完全符合您要求的示例,即使使用与您的问题相同的名称,也可以证明这一点。在假设上述想法只处理一列或另一列而不是组合之前,您应该尝试一下......
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”中插入重复键。
声明已终止。
我最近还写了一篇关于将唯一约束应用于两列的解决方案以任意顺序: