多态关联外键约束。这是一个好的解决方案吗?

时间:2011-10-30 19:23:29

标签: postgresql foreign-keys polymorphic-associations

我们在应用程序中使用多态关联。我们遇到了经典问题:我们遇到了无效的外键引用,我们无法创建外键约束,因为它是一个多态关联。

那就是说,我已经做了很多研究。我知道使用多态关联的缺点和好处。但我发现似乎是一个不错的解决方案:

http://blog.metaminded.com/2010/11/25/stable-polymorphic-foreign-key-relations-in-rails-with-postgresql/

这很好,因为你可以获得两全其美。我担心的是数据重复。我对postgresql没有足够深入的了解,无法完全理解这个解决方案的成本。

你有什么想法?这个解决方案应该完全避免吗?或者这是一个很好的解决方案?

在我看来,唯一的选择是为每种关联类型创建一个外键。但是你会遇到验证只存在一个关联的问题。这是一个“挑选毒药”的情况。多态关联清楚地描述了意图,也使这种情况变得不可能。在我看来,这是最重要的。数据库外键约束是幕后功能,改变“意图”以使用数据库限制对我来说是错误的。这就是为什么我想使用上面的解决方案,假设它没有明显的“避免”。

2 个答案:

答案 0 :(得分:9)

我对PostgreSQL的INHERITS实现的最大问题是你不能设置父表的外键引用。有一个很多的案例你需要这样做。请参阅我的答案末尾的示例。

在Rails之外创建表,视图或触发器的决定是至关重要的。一旦你决定这样做,那么我认为你也可以使用你能找到的最好的结构。

我长期使用基本父表,使用外键强制执行不相交的子类型。此结构保证只能存在一个关联,并且关联解析为父表中的右子类型。 (在Bill Karwin's slideshow on SQL antipatterns中,这种方法从幻灯片46开始。)在简单的情况下,这不需要触发器,但我通常为每个子类型提供一个可更新的视图,并要求客户端代码使用视图。在PostgreSQL中,可更新视图需要编写触发器或规则。 (9.1之前的版本需要规则。)

在最一般的情况下,不相交的子类型没有相同数量或种类的属性。这就是我喜欢可更新视图的原因。

表继承不可移植,但这种结构是。你甚至可以在MySQL中实现它。在MySQL中,您必须使用对一行表的外键引用替换CHECK约束。 (MySQL解析并忽略CHECK约束。)

我认为您不必担心数据重复。首先,我非常确定父表和继承表之间的数据不会重复。它只是出现了这种方式。第二,复制派生的数据,其完整性完全由dbms控制,并不是一个特别痛苦的吞下药。 (但不受控制的重复是。)

考虑删除是否应该级联。

答案 1 :(得分:3)

你不能以简单的方式在数据库中强制执行 - 所以这是一个非常糟糕的主意。最好的解决方案通常是简单的 - 忘记多态关联 - 这是反模式的味道。