正如你所说,
我还可以在 Actions 和 Rules 上设置一个 groupId FK...</p>
我认为这意味着组和规则以及组和操作是“一对多”相关的:一个组可以有许多规则/操作,一个规则/操作只能属于一个组。如果是这样,那么请使用groupId
这些关系的列。
现在要在规则和操作之间建立多对多关系,并限制相关的规则和操作必须属于同一个组,您必须引入一些冗余——特别是复制有关组的信息这两个实体属于。
鉴于此,第三个表 ,RulesActions
可以这样定义:
RuleID
ActionID
GroupID
FOREIGN KEY (RuleID, GroupID)
FOREIGN KEY (ActionID, GroupID)
该GroupID
列是冗余位:显然,可以通过查找相应的表来确定RuleID
' 或' 组。ActionID
但是,如您所见,单列GroupID
用作两者的组参考,从而确保两个项目具有相同的组。并确保组 ID 确实是规则和操作都属于的组 ID(而不仅仅是任意一个),列包含在两个外键中,即RulesActions
表引用Rules
by(RuleID, GroupID)
而不是仅 by RuleID
,并且相同为Actions
.
当然,给定这样的外键定义,目标表中对应的主键或唯一约束也需要以同样的方式定义。我说主键或唯一约束是因为在我使用的产品 SQL Server 中,允许外键引用定义为主键或应用唯一约束的列。因此,在 SQL Server 中,我可以像这样定义Rules
和Actions
表:
Rules
:
RuleID PRIMARY KEY
GroupID FOREIGN KEY
UNIQUE (RuleID, GroupID)
Actions
:
ActionID PRIMARY KEY
GroupID FOREIGN KEY
UNIQUE (RuleID, GroupID)
这将允许我RulesActions
之前指定模式。我不确定许多其他产品是否允许这样做,如果没有,您可以尝试以下方法:
Rules
:
RuleID UNIQUE
GroupID FOREIGN KEY
PRIMARY KEY (RuleID, GroupID)
Actions
:
ActionID UNIQUE
GroupID FOREIGN KEY
PRIMARY KEY (RuleID, GroupID)
这样,UNIQUE 约束仅应用于(实体)ID 列,以确保 ID 的唯一性,并且将外键的目标列集RulesActions
定义为主键,以便您拥有一个通用的 FK <-> PK关系。
请注意,如果事实证明您需要多对多组/规则和/或组/操作关系,则该想法本身将几乎没有变化。对于多对多关系,您需要引入一个映射表,其中 anEntityID, GroupID
是主键,相应的外键需要引用该表而不是主实体表。