让我来布置场景;
我必须谈谈一种将有两种类型的用户的系统。在不赘述的情况下,我们将其称为“超级用户”和“普通用户”。
超级用户可能存在或可能不存在,但如果存在,则始终引用普通用户。普通用户始终存在,但可以被“软”删除。
系统上正在执行升级步骤。所有属于超级用户的普通用户都将获得一个新的超级用户帐户。被软删除的任何普通用户都不能拥有超级用户帐户,即使以前拥有一个也是如此。
我有两个表,Message和ReceivedMessage。
消息包含OnBehalfOfNormalUserId和消息内容。ReceivedMessage包含发送消息的人的SuperUserId。
create table Message(MessageId int identity(1, 1) not null, OnBehalfOfNormalUserId int not null, Subject varchar(50) null, Content varchar(max) not null, constraint PK_MESSAGEID primary key (MessageId), contraint FK_ONBEHALFOFNORMALUSERID (OnBehalfOfNormalUserId) references User (UserId));
create table ReceivedMessage(QueueId int not null, MessageId int not null, SentBySuperUserId int null, constraint PK_QUEUEID primary key (QueueId), constraint FK_QUEUEID (QueueId) references MessageQueue (QueueId), constraint FK_SENTBYSUPERUSERID (SentBySuperUserId) references SuperUser (UserId));
这些表包含的内容不止于此,但对于我的示例而言,就足够了
现在,以前是超级用户的人可能已经由旧系统发送了一条消息,但现在该用户已被软删除,并且不能成为超级用户。这是通过在“ SentBySuperUserId”列中放置“ null”来实现的。但是,除非NormalUser被软删除,否则此列必须包含SuperUserId。迁移后被软删除的所有NormalUser帐户将保留其SuperUser帐户,但将无法访问。(我无法控制此过程,也无法控制/不迁移什么数据)
用户表具有标志“ IsDeleted”。如果已标记,则SentBySuperUserId可以为null,否则为null。(超级用户通过桥表映射到普通用户)
我创建了一个简单的视图,该视图返回SuperUserId为null AND User.IsDeleted = 0的所有NormalUserId。但是,对于索引视图而言,这是不够的,因为就唯一约束而言,一条消息就可以了。鉴于我无法进行子查询,因此无法使用CTE,也无法使用外部联接,因此我不确定如何强制执行确保视图返回恰好0行的约束。
如何在视图上强制执行约束,以确保在MSSQL中返回0行?
您不能,唯一可以应用于视图的约束类型是唯一约束,并且不可能单行违反该约束。
但是,您始终可以将结果加倍,以使其确实违反约束,并且可以声明性地强制执行。
您将需要创建一个表并插入两行。
添加CROSS JOIN dbo.TwoRows
到您的视图定义并在其上创建唯一索引。
现在,原始查询返回的每一行都会加倍。因此,如果原始查询完全返回任何行,它将违反其上的唯一索引。
能够交叉连接到包含两行的虚拟表会更好,但是在索引视图中不允许派生表等。
注意:在我看来,确实有可能定义视图,以便在尝试实现甚至单行(例如除以零)的尝试时都可能导致运行时错误,但这是一个更可怕的解决方案,并且也不能保证该表达式可以正常工作,因为可以在计划中将表达式过滤掉之前对其进行评估。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句