【问题标题】:Foreign key referencing the same table... Can you help explain this example?外键引用同一个表...你能帮忙解释一下这个例子吗?
【发布时间】:2014-06-17 14:53:38
【问题描述】:

如果我有一个约会网站的“用户”表,关系列可以是同一个表中另一个用户主键的外键吗?这是一对一的关系(每个人只能有一个关系伙伴)。该值可以为 null(此人当前未处于恋爱关系中)吗?

在数据库设计中正确的做法是什么?

【问题讨论】:

  • 你描述的方法是正确的方法;除非您不会将其称为 外键,因为 [a] 它不是外键,而 [b] 它不是键。它只是一个恰好与主键具有相同值的列。你为什么怀疑它?你实现它然后遇到问题了吗?
  • 你的例子不清楚。你能添加一个图片表示
  • 我只是不确定有一个单独的“关系”表是否更合适?我没有实现任何东西,但我想完全理解设计概念。我只需要专家建议
  • 我创建了一张图片,但我发现我不能发布它(我需要 10 声望)...还有其他想法吗?
  • 在自我引用中一对一是不可能的。例如。一个主键可以存在多个外键中。

标签: database database-design


【解决方案1】:

是的,但是您将无法强制两个人通过约束相互关联。您必须确保在您的代码中是这种情况。

UserA has relationship with UserB
UserB has relationship with UserA

UserA has relationship with UserB
UserB has no relationship 

UserA has no relationship
UserB has relationship with UserA 

所有这些都是该领域的有效 FK,实际上......

UserA has relationship with UserB
UserB has relationship with UserC

UserA has relationship with UserB
UserC has relationship with UserB

FK 也允许。您需要确保在代码中正确设置两者并围绕更新进行正确的事务处理。

您还可以使关系用户唯一,这至少可以防止最后一种情况。

【讨论】:

  • 哦,好吧!谢谢!那有没有更好的设计方法??
  • 我想不到。您可以确保在更新他们的关系状态时,您是在一次事务中完成的,所以要么全有,要么全无。
【解决方案2】:

你可以把任何你想要的东西放在一张桌子上。您给出一个声明/含义,并将使其正确的行放在表中。查询的含义是其行根据其表的含义而成立。这就是您使用数据库所需的全部内容。

约束来自给定的陈述和可能出现的情况。您声明它们以防止无法出现的状态。

当某些源列的值集必须是目标列的值集的子集时,存在“包含依赖性”约束。如果目标还必须形成其表的键,则存在“外键”约束。目标表是否为源表无关紧要。在 SQL 中有一种语法为“外键”的声明,但因为它的目标必须是唯一的,而不是键,它实际上只定义了一个外键。某些设计方法碰巧专注于某些约束,而忽略了其他约束甚至表含义。

你想到了一些关系(不一定体现在一个表中)

coupled(p,q) // == '[p] & [q] are coupled'
    key {p,q}
    // plus CHECK-expressible constraints only involving coupled

将这个表嵌入到另一个表中只是意味着这些约束将应用于嵌入表的适当部分。

你心里也有(不一定体现在表中)

userfact(p,...) // == '...[p] is such that ...'
    key {p}

如果你声明

userbig(p,...,q) // == userfact(p,...) and coupled(p,q)
    key {p} fk q->p
    // plus coupled-like constraints involving select p,q from userbig

那么你不能记录关于未耦合的 p 的 userfact(p,...)。另外,您必须使用上述选择来查询独立于用户事实的耦合。

如果你让 q 为空,那么你得到

usernull(p,...,q) // == userfact(p,...) and (q is null and not exists q coupled(p,q) or not q is null and coupled(p,q))
    key {p}
    // plus coupled-like constraints involving select p,q from usernull where not q is null

不幸的是,现在您必须使用上面更复杂的选择来查询独立于用户事实的耦合。此外,对应于 fk q->p 的约束不再是 fk 约束而是更复杂,因为 q 可以为空。此外,任何时候您想要 usernull 的任何部分(甚至全部)都可能需要测试 q 的 nullness 以确保使用您想要的行。

最糟糕的是,SQL 运算符的行为很复杂,因为它是 3VL 类型的,所以除了极其简单的查询之外,所有涉及空值的查询的含义都非常复杂。它们不是表格含义的简单组合。应避免使用空值。

所以你真正想要的只是userfactcoupled 及其fk p->userfact.p, q->userfact.p

对于目前的 SQL DBMS,工业上必须不断选择以非声明方式约束性能并在某些表中使用空值(尽可能在查询表达式叶附近删除空值)。但是第一个应该设计得当。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-22
    • 1970-01-01
    • 2017-03-24
    • 1970-01-01
    • 1970-01-01
    • 2015-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多