【问题标题】:Composite primary keys and link table rules复合主键和链接表规则
【发布时间】:2014-09-12 19:54:48
【问题描述】:

我与链接表有多对多关系,我需要形式化一个规则集。以下是我的问题:

左 (L) 和右 (R) (L&R) 表:两者都有复合(感谢 stakx 纠正我)主键。链接表有自己的主键,但显然,因为 L&R 表具有每个复合主键,所以链接表必须包含多个外键。没问题。即

L Table:
LID       (int)      PK1
LSomeDate (DateTime) PK2
Other Fields...

R Table:
RID       (int)      PK1
RSomeDate (DateTime) PK2
Other Fields...

Link Table:
ID        (int)      PK
LID       (int)      FK1
LSomeDate (DateTime) FK1
RID       (int)      FK2
RSomeDate (DateTime) FK2

要求 1:任何一个表中的实体都可以在没有另一个表的情况下存在。所以我们应该在 M:M 的两边都有一个 0:M 而不是 1:M。我猜测(可能是错误的)这意味着我必须将链接表外键保留为空。但如果我这样做,我可以输入 LID 并将 LSomeDate 字段留空。或相反亦然。 RID 和 RSomeDate 也是如此。

我的第一个问题是,创建一些“任何内容(规则、约束、默认值、触发器等)”的标准方法是什么被输入。然后我可以将其应用于 R FK。这将防止在 FK 的一部分中留下空值。

本质上...FK 的整个 L 侧为空,或者两个字段都已填充(有效的参考)。对于 R 也是如此,但这将是分开的。

我的另一个问题是......创建链接表时,L表是否应该包含右表的FKID,反之亦然,例如......上面的L表是否也应该包含RID和RSomeDate作为外​​键,以及在 R 表上反之亦然,或者说这些都在链接表中指定就足够了。

提前致谢。

【问题讨论】:

  • 关于术语的旁注:虽然一个表可以有多个候选键,但它们只能有一个主键。然而,这个主键可能是一个复合键(即由多于一列组成)。我假设您的意思是说您的 L 和 R 表都有一个复合主键?
  • @stakx - 我做到了,并更新了问题。谢谢。 :)
  • 你说的“…强制用户输入…ID”是什么意思?用户是否直接插入数据库?也就是说,您想直接在数据库级别还是在应用程序级别执行此规则?
  • 我正在建数据库,所以还没有开始app dev。我的想法是,由于这是一个数据库问题(与业务逻辑相反),它应该由数据库处理,如果两者都不正确,数据库应该抛出一个可以在应用程序级别捕获的错误。用户可能无法在链接表中输入数据(希望如此),但我想在这里抓住它,因为这意味着更少的代码,我觉得确保数据准确是一个数据库问题。

标签: sql sql-server database


【解决方案1】:

在链接表中有条目的唯一原因是将一条 L 记录链接到另一条 R 记录。如果一个 L 存在而没有与任何 R 链接,则在 L 中有一个记录,但在链接表中将没有 L 和 R 的这种特定组合的条目。

也就是说,N:N 链接表中的条目只有在 L 和 R 关联时才存在。也就是说,如果两条记录 L 和 R 没有链接(“一个存在而没有另一个”),那么链接表中根本不会有条目。因此,链接表中甚至不需要 NULL 值。

意思是,理想情况下,所有链接表列都声明为NOT NULL;突然你的问题就消失了!

(顺便说一句。与您的主键是复合的无关;同样的事实也适用于非复合键。)

尽管如此,如果您仍然想声明这些列 NULLable,并且您想确保在数据库级别,例如链接表中的所有 L 外键都不是部分 NULL,您可以添加 CHECK 约束:

ALTER TABLE LinkTable
ADD CONSTRAINT CK_LinkTable_LID_LSomeDate
CHECK ((LID IS NULL     AND LSomeDate IS NULL    ) 
    OR (LID IS NOT NULL AND LSomeDate IS NOT NULL))

但同样,如果所有这些外键列一开始都是NOT NULLable 会更好,因为这就是 N:N 链接表的设计方式。

【讨论】:

  • 这很有意义……我现在感觉自己像个傻瓜。对不起。我的头很模糊,因为我有多个地方发生这种情况,我正试图理解这一切,因为它是由过去的开发人员完成的。感谢您对此的帮助。
  • @FrancisRodgers:别担心,伙计。我们都是来学习的。 (如果您觉得它有帮助,请随意投票甚至接受答案。;-)
  • 所以如果我理解正确的话。忘记约束,只是不要让链接表中的 FK 为空。这是因为 0:N 可以在任一侧表示,只需在相关侧输入记录,而不是通过链接表将其关联。只有在将一侧链接到另一侧时才需要链接表...对吗?
  • @FrancisRodgers:没错! (链接表将两个表 L 和 R 之间的逻辑 N:M 关系实现为两种关系:L 和链接表之间为 1:N,R 和链接表之间为 1:M。设计合理的链接表永远不会有 0 :* 或 0..1:* 任一侧的基数,只有 1:*.)
  • @FrancisRodgers:关于您的第二个问题:不,在您的情况下,L 表不应该有 R FK(R 表也不应该有 L FK)。在建模 N:M 关系时,只有一个链接表是要走的路。 FK always 模拟与目标表的 *:1 关系(如果 FK 列是 NULLable,则为 *:0..1),这不是您想要的。 (顺便说一句。这就是链接表将 N:M 关系分解为两个关系 1:N 和 M:1 的原因;因为它有两个 FK。)
猜你喜欢
  • 1970-01-01
  • 2018-10-19
  • 2020-03-09
  • 2011-12-21
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
相关资源
最近更新 更多