【问题标题】:How to map different many to manys with same constraint如何使用相同的约束映射不同的多对多
【发布时间】:2011-12-12 20:20:42
【问题描述】:

我有一个数据模型,我对此有些担心。这里是:

我担心的是可以将应用程序分配给成员,然后将来自不同应用程序的角色分配给成员。

现在,我知道我可以对此进行限制以确保不会发生这种情况,但这似乎是一个创可贴。我宁愿设计模型,以便不需要约束。

谁能建议如何更改模型以确保只能从分配给它的应用程序中为成员分配角色?

【问题讨论】:

  • 你的意思是,一个成员只能分配给一个应用程序?或者成员需要在每个应用程序中拥有一个角色……?
  • 我认为您的方案中的约束没有任何问题。我能想到的任何修复都需要一些丑陋的反规范化......
  • 在我看来,模型很好。你想要完成的听起来更像是业务逻辑/应用程序级别的验证。您的应用程序应通过遍历关系来强制执行完整性。如果您想阻止您的应用程序从数据库端执行此操作,您可能会考虑用一个过程来包装它。
  • @Mystere Man,根据您的业务规则,是否可以将成员分配给应用程序但不能分配给分配给该应用程序的角色?
  • @TimLehner - 不,必须为用户分配至少一个应用程序,以及该应用程序中的至少一个角色。它们可以分配给许多应用程序,并分配给任何这些应用程序的角色。不能将它们分配给未分配到的应用程序中的角色。

标签: sql sql-server database-design constraints data-integrity


【解决方案1】:

通常,您在拆分密钥时会遇到此类问题。修复拆分键,然后使用重叠的外键约束通常是您要寻找的。​​p>

create table cmember (
  cmemberid integer primary key,
  username varchar(15) not null,
  emailaddress varchar(64) not null
);

create table application (
  applicationid integer primary key,
  description varchar(50) not null
);

create table member_application (
  cmemberid integer not null references cmember (cmemberid),
  applicationid integer not null references application (applicationid),
  primary key (cmemberid, applicationid)
);

create table role (
  roleid integer primary key,
  rolename varchar(25) not null
);

create table crole (
  croleid integer not null references role (roleid),
  -- Include the application id in this table . . .
  applicationid integer not null references application (applicationid),
  -- and make it part of the primary key.
  primary key (croleid, applicationid)
);

create table member_role (
  cmemberid integer not null references cmember (cmemberid),
  croleid integer not null,
  applicationid integer not null,
  primary key (cmemberid, croleid, applicationid),
  -- Note the overlapping foreign key constraints.
  foreign key (croleid, applicationid) references crole (croleid, applicationid),
  foreign key (cmemberid, applicationid) references member_application (cmemberid, applicationid)
);

insert into cmember values (1, 'A', 'A@b.com');
insert into cmember values (2, 'B', 'B@b.com');

insert into application values (1, 'App 1');
insert into application values (2, 'App 2');

insert into member_application values (1, 1);
insert into member_application values (2, 2);

insert into role values (1, 'Admin');

insert into crole values (1, 1);
insert into crole values (1, 2);

insert into member_role values (1, 1, 1);
insert into member_role values (2, 1, 2);

成员 1 仅分配给应用程序 1。因此尝试插入引用应用程序 2 的行应该会失败。

insert into member_role values (1,1,2);
ERROR:  insert or update on table "member_role" violates foreign key constraint "member_role_cmemberid_fkey1"
DETAIL:  Key (cmemberid, applicationid)=(1, 2) is not present in table "member_application".

【讨论】:

    【解决方案2】:

    是的,

    方法是在Member_Role 中删除CMemberID 的外键,并在此表(Member_Role)中创建一个外键到Member_Application。新的外键必须包含两个字段:ApplicationID + CRoleID

    现在:

    Member_Role ( CMemberID , CROleID )
    PK = CMemberID + CROleID
    FK1 (to CMember) =  CMemberID
    FK2 (to CRole) = CRoleId
    

    解决方案:

    CRole: Create unique constraint on CRoleID + ApplicationID
    Member_Application: create unique constraint on CMemberID + ApplicationID
    Member_Role ( CMemberID , ApplicationID, CRoleID )
    PK = CMemberID + ApplicationID + CRoleID
    FK1 (to Member_Application) = CMemberID + ApplicationID
    FK2 (to CRole) = ApplicationID + CRoleID
    

    【讨论】:

    • 似乎这仍然允许任何角色连接到该成员应用程序
    • 要将角色连接到成员应用程序 CRoleID 并且 ApplicationID 必须匹配。两个都。使用最后一个约束,只有应用程序成员才能获得应用程序角色。
    猜你喜欢
    • 2013-11-29
    • 2020-01-04
    • 2013-06-14
    • 1970-01-01
    • 2012-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-12
    相关资源
    最近更新 更多