如何加入正确的一对一表(超类型,子类型)?

时间:2011-11-17 14:59:12

标签: mysql database normalization one-to-one database-normalization

我一直在研究第一,第二和第三范式,我希望能更好地规范我的表格。我意识到,部分原因是我从未理解一对一表的目的。根据我的理解,“可选”数据应该被分组到另一个表中,使不同的实体保持完整,同时避免在一个整体表中维护几个NULL字段的细微差别。

所以,一个现实世界的场景。在CMS中,我想维护几种不同类型的“页面”,使其可以通过其他插件进行扩展,而不会影响原始模式。到目前为止,我将这些作为样本表:

  • 页面(标题,路径,类型等)
  • ContentPages (与基页相同,但包含关键字/说明/内容字段)
  • LinkedPages (与基页相同,但包含对其他页面的引用)
  • ProductPages (与基页相同,但有SKU和其他与ecomm相关的信息)

到目前为止,这么好。没有NULLS。自我记录的设计。超级打字/子打字在我的PHP模型和数据库之间是一致的。一切都很冷淡。

除了任何页面ID,我不想做第一个查询来获取基页信息,找出它是什么类型的页面,然后用另一个查询获取相应的子类型信息。我是否必须通过应用程序状态(或URL)跟踪此问题,或者是否有办法知道要加入哪个表,而只知道页面ID而没有其他内容?

这很简单,只有一个表(显然),因为NULL字段表示类型,或ENUM可以告诉我它是什么。切换回1NF是不可接受的答案,因为我已经知道如何做到这一点。我想以这种方式学习;)

更新:还想提一下,每个子类型属性对于该类型都是唯一的。因此,所有类型共享的任何公共属性当然都会进入基页表。子类型不会共享任何其他属性。这似乎是对子表进行分组的合理方式,但也许我正在以这种安排打败一对一表的目的......

3 个答案:

答案 0 :(得分:1)

您可以通过左外部连接主Page表上的所有子类型来创建视图。可以通过单个page_id查询视图,并返回一行包含许多空值,与使用一个大的第一个普通表单页表相同。

答案 1 :(得分:1)

这取决于谁在问这个问题。如果您的插件正在驱动查询,那么它可以从其特定的子类型开始并加入它知道必须存在的超类型。

我不知道您的业务需求是什么,但在我看来,如果您试图保持模块化,那么您希望尽可能多地从子端(即插件端)驱动连接。 / p>

如果您要从超类型驱动查询到子类型,那么您可以使用外部联接,只需在代码中准备好处理空列,如果所涉及的子类型不存在。显然,这种方法不那么模块化,但我认为有时候这就是你需要或想做的事情。

答案 2 :(得分:1)

  

有没有办法知道要加入哪个表,而只知道   页面ID,没有别的?

好吧,在超类型/子类型结构中,您应该知道的不仅仅是页面ID。您还应该知道子类型。

通常,'n'子类型的超类型/子类型结构映射到

  • n + 1个表,每个子类型一个,加上一个超类型,
  • n可更新视图,每个视图都使用适当的子类型连接超类

因此,您的应用程序通常应该使用视图,而不是使用基表。 (通常,但并非总是如此。)

如果您没有使用视图,那么当您从超类型中检索页面ID号时,您还应该检索标识子类型的列。没有这样的专栏?修复它。对于带代码的超类型/子类型,结构描述及其背后的逻辑,请参阅其他相关SO database design problem