【问题标题】:storing preferred entry in a 1-to-n database relation在 1 对 n 数据库关系中存储首选条目
【发布时间】:2018-08-11 23:47:27
【问题描述】:

我正在寻找如何(最好)为关系数据库建模,以便它可以标记 1:n 关系中的(0 或 1)个条目是首选的。

(它实际上是在 mariadb 10.2 中实现的,但这并不重要)

为简单起见,假设我有两个表:

父母:

  • 身份证
  • 姓名

孩子:

  • 身份证
  • 姓名
  • parentid (FK -> parent(id) )

问题是我需要建模一种存储首选子项的方法

我看到了两种方法,但我不太喜欢任何一种:

  1. 在父项中添加一个字段,列出首选子项的 id,并将其作为子项的 FK。
  2. 在子项中添加一个布尔列以指示一行是首选子项。

我看到的东西:

只有 1 个首选孩子:

  • 在解决方案 1 的情况下,我只能有一个最大值。一个首选的孩子(=好)

  • 在解决方案 2 的情况下,我需要依靠应用程序为每个父母只指定一个首选孩子 (=bad)

-> 这将我推向解决方案 1

可维护性

解决方案 1 在父表和子表之间的双向创建 FK。我不相信这样的结构如何能够持续下去,例如如果需要备份/恢复周期,因为没有更多的创建表的顺序,它们需要在没有 FK 的情况下创建,然后需要稍后添加。即使这些都被工具所覆盖,我仍然很害怕长期可维护性。

-> 这将我推向解决方案 2

所以在我们选择一个解决方案之前,我不相信这两个都不是一个好的解决方案,有人有其他解决方案需要考虑吗?

还有什么我忽略的要考虑的吗?

我不确定如何考虑标准化。

编辑:

在键入此内容后进一步挖掘,我想出了第三个看起来更好的选项:添加第三个表来为首选子级建模。

基本上:

首选孩子:

  • 父代
  • childid

全部带有 FK,例如
FOREIGN KEY (parentid, childid) REFERENCES child (parentid, id)

可能还有一些更独特的键来确保它是唯一的,但这解决了我上述解决方案 1 的鸡蛋问题,并避免了应用程序在解决方案 2 中可能造成的混乱。

在这第三个选项中,我做了一个快速的处理:http://sqlfiddle.com/#!9/af77bf/5/0

【问题讨论】:

    标签: database-design foreign-keys database-normalization


    【解决方案1】:

    我会选择选项(2)。

    在PostgreSQL,AFAIK中,没有partial UNIQUE constraint,但是有partial UNIQUE index,可以用来保证相同parentId的多行只有1个preferred

    假设列preferred 的类型为boolean。您可以在列parentid + preferred 上创建partial UNIQUE index,其中preferred 为真。

    CREATE UNIQUE INDEX unique_parentid_preferred ON child (parentid, preferred) WHERE preferred is true;
    

    添加具有相同parentidpreferred = true 的行时会引发此错误:

    ERROR:  duplicate key value violates unique constraint "unique_parentid_preferred" ...
    

    【讨论】:

    • mariadb 非常像 mysql。 AFAIK 既不支持部分唯一索引。但如果是这样,那确实是防止数据污染的解决方案。
    【解决方案2】:

    选项 1 还不错,但需要一个可为空的首选 child_id 或临时禁用 FK 检查才能填充。尽管如此,它在查询首选子节点时仍然有效地使用了普通的 PK 和 FK 索引。

    选项 2 不是一个好的解决方案 IMO,因为首选子标志会在行之间创建依赖关系。更新首选子项需要更新多行,从而产生不一致的机会。它实际上可以在 MySQL / MariaDB 中以某种方式处理 - 如果您愿意将 NULL 用于 FALSE,(parent_id, is_preferred) 上的唯一索引将只允许 is_preferred = TRUE 的一行,is_preferred = NULL 的任意数量的行.但是你必须处理 NULL,这会增加一些复杂性,并且存在非 NULL 非 TRUE 值的风险。

    选项 3 很好。它很简单,避免了使其他选项复杂化的问题,同时只要您为 PK / FK 字段编制索引,就可以有效地使用索引。

    【讨论】:

      猜你喜欢
      • 2010-11-26
      • 2020-04-10
      • 1970-01-01
      • 2014-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多