为两列的组合添加唯一约束
我有一个桌子,不知何故,同一个人进入我的Person
表两次。 现在,主键只是一个自动编号,但还有两个其他的字段,我想迫使它们是唯一的。
例如,这些字段是:
ID Name Active PersonNumber
我只想要一个唯一的PersonNumber和Active = 1的logging。
(所以这两个领域的组合需要是唯一的)
什么是在SQL服务器现有的表上最好的办法我可以做到这一点,如果任何人做一个插入与现有值相同的值,它会失败,所以我不必担心在我的应用程序代码中的这一点。
一旦你删除了你的副本:
ALTER TABLE dbo.yourtablename ADD CONSTRAINT uq_yourtablename UNIQUE(column1, column2);
要么
CREATE UNIQUE INDEX uq_yourtablename ON dbo.yourtablename(column1, column2);
当然,在让SQL Server尝试插入行并返回一个exception(exception是昂贵的)之前,首先检查这个违规通常会更好。
http://www.sqlperformance.com/2012/08/t-sql-queries/error-handling
如果要防止exception冒泡到应用程序,而不更改应用程序,则可以使用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
但是,如果你不告诉用户他们没有执行插入,他们会想知道为什么数据不在那里,没有例外报告。
编辑这里是一个例子,完全按照你的要求,即使使用相同的名称作为你的问题,并certificate这一点。 你应该尝试一下,假设上述想法只处理一列或另一列,而不是组合…
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违反唯一键约束“uq_Person”。 不能在对象'dbo.Person'中插入重复的键。 声明已经终止。
这也可以在GUI中完成:
- 在“Person”表下,右键单击Indexes
- 点击/hover新索引
- 点击非聚集索引…
- 将会给出一个默认的索引名称,但您可能想要更改它。
- 选中唯一checkbox
- 点击添加…button
- 检查你想包括的列
- 在每个窗口中单击确定 。