关于postgresql:多态关联外键约束。

Polymorphic association foreign key constraints. Is this a good solution?

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

也就是说,我做了很多研究。我知道使用多态关联的缺点和好处。但我发现了一个看起来不错的解决办法:

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

这很好,因为你在两个世界中都得到了最好的。我担心的是重复数据。我对PostgreSQL没有足够的了解,无法完全理解这个解决方案的成本。

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

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


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

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

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

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

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

我认为您不必担心重复数据。首先,我很确定父表和继承表之间的数据不会重复。看起来就是这样。第二,复制或派生的数据,其完整性完全由DBMS控制,这不是一个特别痛苦的药丸。(但不受控制的复制是。)

考虑一下删除是否应该级联。

  • 带有SQL代码的发布示例。
  • 带有SQL代码的"参与方"示例。


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