我有一张桌子,不知何故,同一个人两次进入我的Person
牌桌。现在,主键只是一个自动编号,但还有另外两个字段,我想强制它们是唯一的。
例如,字段为:
ID
Name
Active
PersonNumber
我只想要一张具有唯一PersonNumber且Active = 1的记录。
(因此两个字段的组合必须是唯一的)
SQL服务器中现有表的最佳方法是什么?如果其他人使用与现有值相同的值进行插入操作,它会失败,所以我不必在我的应用程序中担心这一点代码。
答案 0 :(得分:175)
删除副本后:
ALTER TABLE dbo.yourtablename
ADD CONSTRAINT uq_yourtablename UNIQUE(column1, column2);
或
CREATE UNIQUE INDEX uq_yourtablename
ON dbo.yourtablename(column1, column2);
当然,在让SQL Server尝试插入行并返回异常(异常很昂贵)之前,首先检查此违规通常会更好。
http://www.sqlperformance.com/2012/08/t-sql-queries/error-handling
如果您想防止异常冒泡到应用程序,而不更改应用程序,您可以使用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
最后一次插入的错误消息:
Msg 2627,Level 14,State 1,Line 3 违反UNIQUE KEY约束'uq_Person'。无法在对象'dbo.Person'中插入重复键。 声明已经终止。
答案 1 :(得分:10)
这也可以在GUI中完成:
答案 2 :(得分:4)
就我而言,我需要允许许多非活动状态,并且只允许两个键的组合处于活动状态,如下所示:
UUL_USR_IDF UUL_UND_IDF UUL_ATUAL
137 18 0
137 19 0
137 20 1
137 21 0
这似乎可行:
CREATE UNIQUE NONCLUSTERED INDEX UQ_USR_UND_UUL_USR_IDF_UUL_ATUAL
ON USER_UND(UUL_USR_IDF, UUL_ATUAL)
WHERE UUL_ATUAL = 1;
这是我的测试用例:
SELECT * FROM USER_UND WHERE UUL_USR_IDF = 137
insert into USER_UND values (137, 22, 1) --I CAN NOT => Cannot insert duplicate key row in object 'dbo.USER_UND' with unique index 'UQ_USR_UND_UUL_USR_IDF_UUL_ATUAL'. The duplicate key value is (137, 1).
insert into USER_UND values (137, 23, 0) --I CAN
insert into USER_UND values (137, 24, 0) --I CAN
DELETE FROM USER_UND WHERE UUL_USR_ID = 137
insert into USER_UND values (137, 22, 1) --I CAN
insert into USER_UND values (137, 27, 1) --I CAN NOT => Cannot insert duplicate key row in object 'dbo.USER_UND' with unique index 'UQ_USR_UND_UUL_USR_IDF_UUL_ATUAL'. The duplicate key value is (137, 1).
insert into USER_UND values (137, 28, 0) --I CAN
insert into USER_UND values (137, 29, 0) --I CAN
答案 3 :(得分:0)