我有三张桌子:
1) 应用程序 (AppId, 名称)
2) 屏幕 (ScreenId, 名称)
3) 关系 (AppId, ScreenId)
现在我想对相关表应用一些限制:同一个屏幕可以分配给多个应用程序,但不能有两个同名的屏幕分配给同一个应用程序。
我知道我可以将 Screen.Name 添加到关系表中,然后在 AppId 和 Screen.Name 上创建 PK,但我不想要这样的解决方案,因为 Screen.Name 可能会发生变化。
我有什么额外的选择来实现这样的限制?
我有三张桌子:
1) 应用程序 (AppId, 名称)
2) 屏幕 (ScreenId, 名称)
3) 关系 (AppId, ScreenId)
现在我想对相关表应用一些限制:同一个屏幕可以分配给多个应用程序,但不能有两个同名的屏幕分配给同一个应用程序。
我知道我可以将 Screen.Name 添加到关系表中,然后在 AppId 和 Screen.Name 上创建 PK,但我不想要这样的解决方案,因为 Screen.Name 可能会发生变化。
我有什么额外的选择来实现这样的限制?
您可以基于和表创建索引视图并在那里应用唯一约束。Relation
Screen
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