条件唯一约束

np-*_*ard 88 sql sql-server sql-server-2005

我有一种情况,我需要对一组列强制执行唯一约束,但只对列的一个值.

所以例如我有一个像Table(ID,Name,RecordStatus)这样的表.

RecordStatus只能有一个值1或2(活动或删除),我只想在RecordStatus = 1时创建一个唯一约束(ID,RecordStatus),因为我不关心是否有多个已删除的记录具有相同的ID.

除了编写触发器,我可以这样做吗?

我正在使用SQL Server 2005.

I a*_*ica 137

看,过滤指数.从文档(强调我的):

过滤索引是一种优化的非聚簇索引,特别适用于覆盖从明确定义的数据子集中进行选择的查询.它使用过滤谓词来索引表中的一部分行.与全表索引相比,精心设计的筛选索引可以提高查询性能,并降低索引维护和存储成本.

这是一个将唯一索引与过滤谓词相结合的示例:

create unique index MyIndex
on MyTable(ID)
where RecordStatus = 1;
Run Code Online (Sandbox Code Playgroud)

这实质上实施唯一性的ID时候RecordStatus1.

注意:筛选的索引是在SQL Server 2008中引入的.对于早期版本的SQL Server,请参阅此答案.


D. *_*ick 36

像这样添加一个检查约束.不同的是,如果Status = 1且Count> 0,则返回false.

http://msdn.microsoft.com/en-us/library/ms188258.aspx

CREATE TABLE CheckConstraint
(
  Id TINYINT,
  Name VARCHAR(50),
  RecordStatus TINYINT
)
GO

CREATE FUNCTION CheckActiveCount(
  @Id INT
) RETURNS INT AS BEGIN

  DECLARE @ret INT;
  SELECT @ret = COUNT(*) FROM CheckConstraint WHERE Id = @Id AND RecordStatus = 1;
  RETURN @ret;

END;
GO

ALTER TABLE CheckConstraint
  ADD CONSTRAINT CheckActiveCountConstraint CHECK (NOT (dbo.CheckActiveCount(Id) > 1 AND RecordStatus = 1));

INSERT INTO CheckConstraint VALUES (1, 'No Problems', 2);
INSERT INTO CheckConstraint VALUES (1, 'No Problems', 2);
INSERT INTO CheckConstraint VALUES (1, 'No Problems', 2);
INSERT INTO CheckConstraint VALUES (1, 'No Problems', 1);

INSERT INTO CheckConstraint VALUES (2, 'Oh no!', 1);
INSERT INTO CheckConstraint VALUES (2, 'Oh no!', 2);
-- Msg 547, Level 16, State 0, Line 14
-- The INSERT statement conflicted with the CHECK constraint "CheckActiveCountConstraint". The conflict occurred in database "TestSchema", table "dbo.CheckConstraint".
INSERT INTO CheckConstraint VALUES (2, 'Oh no!', 1);

SELECT * FROM CheckConstraint;
-- Id   Name         RecordStatus
-- ---- ------------ ------------
-- 1    No Problems  2
-- 1    No Problems  2
-- 1    No Problems  2
-- 1    No Problems  1
-- 2    Oh no!       1
-- 2    Oh no!       2

ALTER TABLE CheckConstraint
  DROP CONSTRAINT CheckActiveCountConstraint;

DROP FUNCTION CheckActiveCount;
DROP TABLE CheckConstraint;
Run Code Online (Sandbox Code Playgroud)

  • 这适用于插入,但似乎不适用于更新.EG在我没想到的时候,在其他插入之后添加这个.INSERT INTO CheckConstraint VALUES(1,'No ProblemsA',2); 更新CheckConstraint设置Recordstatus = 1其中name ='No ProblemsA' (3认同)

Car*_*ter 10

您可以将已删除的记录移动到缺少约束的表中,并且可能使用具有两个表的UNION的视图来保留单个表的外观.

  • 这实际上是非常聪明的卡尔.这不是问题本身的答案,但它是一个很好的解决方案.如果表有很多行,那么也可以加快查找活动记录的速度,因为您可以查看活动记录表.它还会加速约束,因为唯一约束使用索引而不是我在下面写的必须执行计数的检查约束.我喜欢. (2认同)