MS SQL服务器交叉表约束
问题描述:
我有三个表:MS SQL服务器交叉表约束
1)应用(的AppId,名称)
2)屏幕(ScreenId,名称)
3)关系式(的AppId,ScreenId)
现在我想对相关表应用一些限制: 可以将同一个屏幕分配给多个应用程序,但不能有两个同名分配给相同应用程序的屏幕。
我知道我可以将Screen.Name添加到关系表中,然后在AppId和Screen.Name上创建PK,但我不想要这样的解决方案,因为Screen.Name可能会更改。
我有什么额外的选择来实现这种限制?
答
您可以创建基于Relation
和Screen
表的indexed view和应用的唯一约束存在。
create view DRI_UniqueScreens
with SCHEMABINDING
as
select r.AppId,s.Name
from
[Schema].Relation r
inner join
[Schema].Screen s
on
r.ScreenId = s.ScreenId
GO
CREATE UNIQUE CLUSTERED INDEX IX_DRI_UniqueScreens
on DRI_UniqueScreens (AppId,Name)
答
这不是一个好的解决方案,但是您可以添加触发器到屏幕和关系表中,只检查您修改的内容是否符合您的条件,如果不是,则回滚。
CREATE TRIGGER trgScreen ON Screen FOR INSERT, UPDATE
AS
BEGIN
IF EXISTS (SELECT r.AppID, s.Name FROM Screen s
INNER JOIN Relation r ON s.ScreenID = r.ScreenID
GROUP BY r.AppID, s.Name
HAVING count(*) > 1)
ROLLBACK TRANSACTION
END
CREATE TRIGGER trgRelation ON Relation FOR INSERT, UPDATE
AS
BEGIN
IF EXISTS (SELECT r.AppID, s.Name FROM Screen s
INNER JOIN Relation r ON s.ScreenID = r.ScreenID
GROUP BY r.AppID, s.Name
HAVING count(*) > 1)
ROLLBACK TRANSACTION
END
+0
是的,触发器将工作,但我尽量避免触发器。 – 2013-05-01 08:00:00
我想知道是否有这样的事情。 :)比触发器好得多。 :) – Jonathan 2013-05-01 07:46:26
更改屏幕名称时,此方法会“验证”数据,还是仅在访问视图时检查数据? – 2013-05-01 07:59:17
@AlexDn - 是的,这将强制在基础表中进行更改时执行约束。如果你转到我链接的页面,你会注意到索引视图有很多限制。这些限制中的大多数存在*,因为它们允许以有效的方式在基表中的每个事务上发生所需的维护活动。 – 2013-05-01 08:09:58