如何将可选的多对多关系添加到另一个多对多关系 table?

How add an optional many to many relationship to another many to many relation table?

我定义了以下 table:

- Group
  - GroupID (pk - int)
  - ...

- Item
  - ItemID (pk - int)
  - ...

- Groups_Items
  - GroupID (pk - int)
  - ItemID (pk - int)

GroupID 上有一个 FK 链接到组 table,ItemID 上有一个 FK 链接到项目 table。

我需要向 Groups_Items table 添加可选关系,即 RuleSetId

- Groups_Items
  - GroupId (pk - int)
  - ItemId (pk - int)
  - RuleSetId (int - nullable)

规则集 table 定义如下:

- RuleSet
  - RuleSetId (int)
  - RuleId (int)

规则table定义如下:

- Rule
  - RuleId (int)
  - ...

当我尝试使用 RuleSet table 中的 RuleSetId 添加 FK 到 Groups_Items table 中的 RuleSetId 时,它给我一个错误,告诉我我没有允许。

每个项目都必须与一个组相关联,一个组可以有多个项目,但我想提供选项以允许一个或多个规则通过规则集与一个项目相关联。请注意,我不想将规则集直接关联到项目本身,而是关联到与组关联的项目,因为项目可能相同但关联到不同的组,并且可能会应用不同的规则集,具体取决于项目的组属于.

我希望这是有道理的。

我正在努力让它工作,所以我一定是设计不正确,但我不确定如何最好地解决这个问题。

更新 - 1

这是我要实现的目标的图表。请注意,我同时添加了 RuleSet table,它只包含一个主键,即 RuleSetId

当我尝试在 GroupsItems table 和 RuleSet table 之间添加关系时出现以下错误:

The ALTER TABLE statement conflicted with the FOREIGN KEY constraint 
"FK_GroupsItems.ERuleSet". The conflict occurred in database 
"MyDatabase", table "dbo.RuleSet", column 'RuleSetId'.

当我尝试在 RuleSet table 和 RuleSetRules table 之间添加关系时出现以下错误:

Unable to create relationship 'FK_RuleSetsRules.RuleSet'.
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint 
"FK_RuleSetsRules.RuleSet". The conflict occurred in database "MyDatabase", 
table "dbo.RuleSet", column 'RuleSetId.

更新:请注意,在这个回答中,我已经更改了您的 'ruleset' table 的含义。在此答案中,规则集 table 创建每个规则集(但不是规则)。 RulesetID 是一个 int 和 PK。然后规则链接到 Ruleset_Rules.

中的此规则集

我相信规则集 table 也需要有一个由外键引用的主键。我建议 Ruleset 和 Rules 也得到一个 many-to-many table 链接它们(如果你想 re-use 规则)或将 RulesetID 作为规则中的一个字段。这个例子有 many-to-many:

CREATE TABLE Grp (GroupID int PRIMARY KEY)
CREATE TABLE Item (ItemID int PRIMARY KEY)

CREATE TABLE RuleSet(RulesetID int PRIMARY KEY)
CREATE TABLE Rules(RuleID int PRIMARY KEY)
GO

CREATE TABLE RuleSet_Rules (RulesetID int, RuleID int, PRIMARY KEY (RulesetID, RuleID))
CREATE TABLE Grp_Item (GroupID int, ItemID int, RuleSetID int, PRIMARY KEY (GroupId, ItemId))
GO

ALTER TABLE [dbo].[Grp_Item] ADD CONSTRAINT [FK_Grp_Item_Grp] FOREIGN KEY([GroupID]) REFERENCES [dbo].[Grp] ([GroupID])
GO
ALTER TABLE [dbo].[Grp_Item] ADD CONSTRAINT [FK_Grp_Item_Item] FOREIGN KEY([ItemID]) REFERENCES [dbo].[Item] ([ItemID])
GO
ALTER TABLE [dbo].[Grp_Item] ADD CONSTRAINT [FK_Grp_Item_Ruleset] FOREIGN KEY([RulesetID]) REFERENCES [dbo].[RuleSet] ([RulesetID])
GO

这里有一个 db<>fiddle,其中包含设置和示例插入。

更新:这是来自下方评论的 updated DB<>fiddle。这有更多的 FK 以及一些插入故意失败的解释。

请注意,这假设 group/item 的每个组合都可以分配 0 或 1 个规则集。如果您需要多个规则集,在 many-to-many table for Grp_Item.

中会变得稍微复杂一些

另请注意,我并未创建所有 FK - 仅创建与 Grp_Item 中的当前问题相关的那些。

With the Ruleset table defined as follows:

- RuleSet
  - RuleSetId (int)
  - RuleId (int)

and the Rule table is defined as follows:

- Rule
  - RuleId (int)
  - ...

When I try to add an FK using the RuleSetId from the RuleSet table to the RuleSetId from the Groups_Items table, it's giving me an error telling me I'm not allowed.

Note that I don't want to associate the ruleset directly to the item itself but to the item associated to the group as the item could be the same but associated to different groups and a different set of rules may apply depending on the group the item belongs to.

通过将 RuleSetId 添加到 Groups_Items table,RuleSet 和 Items 之间存在显式关联,这是您不希望看到的。目前,RuleSet table 仅包含主键和 RuleId,缺少 GroupId。我认为您正在寻找这样的东西:

规则集 table 定义如下:

- RuleSet
  - RuleSetId (pk - int)
  - GroupID (fk - int)
  - RuleId (fk - int)

规则table定义如下:

- Rule
  - RuleId (pk - int)
  - ...

现在 RuleSet table 包含 GroupId 和 RuleId 之间的关系,因此没有理由将 RuleSetId 添加到 Groups_Items table。

最简单的方法是从头开始。使用 editor 创建 DDL(模式)。

-- Rule RUL exists.
--
rule {RUL}
  PK {RUL}
-- Rule set RST exists.
--
rset {RST}
  PK {RST}
-- Rule RUL is member of rule set RST.
--
rule_rset {RST, RUL}
       PK {RST, RUL}

FK1 {RST} REFERENCES rset {RST}
FK2 {RUL} REFERENCES rule {RUL}
-- Item ITM exists.
--
item {ITM}
  PK {ITM}
-- Group GRP exists.
--
group {GRP}
   PK {GRP}
-- Item ITM is member of group GRP.
--
item_group {GRP, ITM}
        PK {GRP, ITM}

FK1 {ITM} REFERENCES item  {ITM}
FK2 {GRP} REFERENCES group {GRP}
-- Set of rules RST applies to item ITM in group GRP.
--
item_group_rset {GRP, ITM, RST}
             PK {GRP, ITM}

FK1 {GRP, ITM} REFERENCES item_group {GRP, ITM}

FK2 {RST} REFERENCES rset {RST}

注:

All attributes (columns) NOT NULL

PK = Primary Key
FK = Foreign Key