ruby-on-rails - 我如何最好地表示一个 child 是特例的一对多关系?

标签 ruby-on-rails database cardinality

我有一个架构,其中两个实体之间存在父子关系。它是一对多的,因此自然会实现为:

table Parents
  id

table Children
  id
  parent_id

但是,我还需要将其中一个 child 作为特例(我们称其为“提升” child )。我可以想到几种方法来做到这一点,包括:

只需在 Children 上添加一个属性:

table Parents
  id

table Children
  id
  parent_id
  is_promoted

这显然是有缺陷的,因为数据库不能保证一致性(至少不能通过常规的外键约束)

Parents 表上创建一个外键:

table Parents
  id
  promoted_child_id

table Children
  id
  parent_id

这是我的第一个倾向,但它确实有明显的循环依赖的缺点,所以可能不是最优的。

我能想到的另一个选择是在 Children 表上放置第二个外键:

table Parents
  id

table Children
  id
  parent_id
  promoted_parent_id

这让我可以放置一个唯一索引,从而加强数据库的一致性。这样做的一个问题是,可能存在一种无意义的关系,其中 parent A 的 child 列为 parent B 的晋升者。

我能想到的最后一个选择是创建一个中间表,例如:

table Parents
  id

table Children
  id

table ParentChildRelationship
  parent_id
  child_id
  is_promoted

同样,我可以在 parent_id+is_promoted 上声明一个唯一约束,以加强一致性。我对此有点矛盾,因为将关系提升为完整实体似乎有点矫枉过正,尽管我在其上放置属性的那一刻(本质上是 is_promoted 是),我想这是有道理的.

我想知道您认为处理此问题的规范方法是什么。特别是,我正在使用 Rails,因此这可能会影响最实用的解决方案。

最佳答案

我没有任何 Rails 经验,但在处理 1 到多个关系的默认值时遇到过类似的情况,并且通常对数据库模式使用类似这样的东西:

table Parents
  id

table Children
  id
  parent_id
  FK (parent_id) references Parents(id)

table PromotedChildren
  child_id
  parent_id
  FK (child_id, parent_id) references Children(id, parent_id)
  UNIQUE Key parent_id

编辑

在回答这个问题后,我开始思考为什么我更喜欢这种表示而不是其他表示,所以我做了更多的研究并给了它更多的思考:

table Parents
  id

table Children
  id
  parent_id
  is_promoted

Jef 提出的对 (parent_id, is_promoted) 的唯一约束将在数据库忽略空值时起作用,正如 Kelvin 所建议的那样,这可能是一个不错的选择。但是,有些人可能会争辩说,使用 null 代替 false/0 是对 null 的错误使用,它有效地将字段转换为三态,即 1、0、unknown。此外 (parent_id, is_promoted) 不是 superkey因此违反了Domain Key Normal Form .

table Parents
  id
  promoted_child_id

table Children
  id
  parent_id

正如您所指出的,这可能会导致循环,并且通过使 promoted_child_id 成为引用 Children(id) 的 FK,您仍然面临数据库异常的风险,其中 ParentA 将 ParentB 的 child 列为已提升。

table Parents
  id

table Children
  id
  parent_id
  promoted_parent_id

在这里,您会遇到所描述的异常风险; promoted_pa​​rent_id 上的唯一键也必须依赖数据库忽略空值;多个级联路径;作为 promoted_pa​​rent_id 和 parent_id 的冗余应该是相同的;更新 parent_id 与 promoted_pa​​rent_id 不匹配的异常。

table Parents
  id

table Children
  id

table ParentChildRelationship
  parent_id
  child_id
  is_promoted

这看起来更像是 parent 对 child 的多对多表示。它提出了与上述其他问题类似的问题。

至于rails开发什么最实用我不好说。我已经使用了我提出的表示法和 Jef 的 C# 和 PHP 表示法,并没有真正注意到差异。

关于ruby-on-rails - 我如何最好地表示一个 child 是特例的一对多关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14135700/

相关文章:

ruby-on-rails - 即使没有 worker 在工作,sidekiq 也会利用内存

c# - 在 C# 中将数据从 nvarchar 转换为 varchar

database - 第一范式和时间数据

sql - PostgreSQL:如何实现最小基数?

mysql - rails 服务器中的数据库存储在哪里?

ruby-on-rails - Rails 简单搜索

ruby-on-rails - 强制has_many但只有一个当前关联的 “rails way”是什么?

php - 将多个图像从 MySQL 数据库拉取到 Android 设备的最有效方法

mysql - 显示表状态的疯狂基数计数

c++ - 如何在 C++ 中将大小动态分配给数组?