Sql server 唯一约束,仅当字段值在将来时

Sql server 唯一约束,仅当字段值在将来时,sql-server,tsql,sql-server-2012,Sql Server,Tsql,Sql Server 2012,多年来,我设计的大多数表都有一个deactivatedate字段。我喜欢这种方法,因为它允许我查看记录何时被停用,并且当我有一个通过触发器记录其历史的表(用作审计停用日期)时,它有双重用途 我现在面临的问题是,是否可以添加一个约束,仅当记录处于活动状态时才强制执行某种唯一性?我想这可以在一个触发器中完成,但我真的试图避免它们。如果DeactivatedDate为null或DeactivatedDate>getdate(),则该记录被视为活动记录 is null检查很容易-此SQL运行良好: AL

多年来,我设计的大多数表都有一个deactivatedate字段。我喜欢这种方法,因为它允许我查看记录何时被停用,并且当我有一个通过触发器记录其历史的表(用作审计停用日期)时,它有双重用途

我现在面临的问题是,是否可以添加一个约束,仅当记录处于活动状态时才强制执行某种唯一性?我想这可以在一个触发器中完成,但我真的试图避免它们。如果
DeactivatedDate为null或DeactivatedDate>getdate()
,则该记录被视为活动记录

is null检查很容易-此SQL运行良好:

ALTER TABLE dbo.PersonHun ADD 
    IsActive AS CASE WHEN DeactivatedDate IS NULL THEN 1 ELSE 0 END
GO

CREATE UNIQUE NONCLUSTERED INDEX uix_PersonHun_RecordNum
    ON PersonHun(RecordNum, OwnedByDataProvider, IsActive)
    WHERE RecordNum IS NOT NULL
GO
但是,只要我将check getdate()的条件添加到computed字段,就会出现以下错误:

Msg 2729,16级,状态1,第7行,表中的“IsActive”列 “PersonHun”不能用于索引或统计信息,也不能用作分区 键,因为它是不确定的

生成错误的代码是:

ALTER TABLE dbo.PersonHun ADD 
    IsActive AS CASE WHEN DeactivatedDate IS NULL 
        OR DeactivatedDate > GETDATE() -- This line here is the culprit
    THEN 1 ELSE 0 END
GO

-- Error occurs when creating the INDEX:
CREATE UNIQUE NONCLUSTERED INDEX uix_PersonHun_RecordNum
    ON PersonHun(RecordNum, OwnedByDataProvider, IsActive)
    WHERE RecordNum IS NOT NULL 
GO
所以我想我的问题是:有没有比使用触发器更好的方法来基于
getdate()
强制某种滚动唯一约束

更新:谢谢你们的评论,但我觉得这有点离题了

我可能没有强调在将来对日期字段的唯一约束的重要性。我的示例中的“IsActive”计算字段不是我需要的(甚至不是我想要的)——它只是一次尝试,只在将来的日期创建一个唯一的约束条件


我不想以任何方式更改此表的架构,因为这会影响外部进程。停用日期字段在这个表中已经建立了多年,我不想改变它。我想我需要使用触发器。

为什么不将IsActive作为实际的布尔/位字段,而不是依赖于其他字段是否有值?将未知值(NULL)解释为另一个因素通常被认为是不好的做法,因为您真的不知道NULL是未设置的还是有意设置的(当然,在您的示例中,您可能会这样做,但一般来说,因为NULL是“未知的”)。所以,如果是我,我会把IsActive变成一个真实的列,并且仍然保留deactivate date作为历史记录/日志记录的目的。人类可以很容易地推断出发生了什么,但是SQL Server可能(如果它支持这一点的话)必须在
GETDATE()
发生更改时(每秒300次)重新检查表中的每一行。谢谢您的回复。到目前为止,我从未因为这样做而遇到任何缺点。我更喜欢使用DeactivateDate,因为它允许我在将来安排记录删除,而无需运行作业。我不同意NULL表示未知,它应该不表示任何内容,如果它处于活动状态,这对于DeactivatedDate是正确的。我认为这两种方法都有利弊。我只是想尽量减少对现有查询的影响,这个表有大量的数据和大量的查询。为什么不将该列设置为-alter table dbo.PersonHun add isActive bit,然后使用update语句将其值设置为-update dbo.PersonHun set isActive=1,其中DISACTIVATEDATE为null或DISACTIVATEDATE>getdate(),然后创建索引。这样,您的索引也将防止您在将来输入重复的列。对于一个不断从多个源更新的表来说,这似乎是一项很大的工作。坦白地说,我根本不想让我动。我只是想设置一个唯一的约束,我想一个计算字段可以满足我的需要。除了不能基于任何不确定的内容(如getdate())之外,它可以