鸡肉和鸡蛋:数据库设计

时间:2011-12-08 09:01:06

标签: mysql database-design content-management-system normalization

我有这张桌子,我打赌看着桌子,你会知道我的问题:)

content_table
--------------------------------------
| id |   title   | type  | parent_id |
--------------------------------------
| 0  |   Root    | Page  |    0      |
|100 |   Home    | Page  |    1      |
|101 | Main Text |Section|    1      |
|102 |   About   | Page  |    1      |
|301 |    Foo    | Text  |   245     |
|302 | About Us  | Text  |   246     |
--------------------------------------

paging_table
---------------------------------
| page_id | section_id | rel_id |
---------------------------------
|   0     |     0      |    1   |
|  100    |    101     |   245  |
|  102    |    101     |   246  |
---------------------------------

section_options
----------------------------
| section_id | option_mask |
----------------------------
|   101      |   65535     |
----------------------------
*paging_table.page_id and paging_table.section_id 
  both have FOREIGN KEYs on content_table.id

 section_options.section_id has a FOREIGN KEY on content_table.id

所以基本上我有一个CMS,我想将一切视为一种内容,无论是页面,页面部分还是页面本身的实际内容。

其次,由于某些页面部分非常相似,我决定不需要创建多个部分(例如 home_main_text about_main_text 等等)。我只需要创建一个通用部分并让paging_table处理其余部分,因为部分也会有很多显示选项(存储在另一个引用content_table.id的表中) 。如果我要将类似的部分与非常相似的选项存储在两行中,那看起来会不好吗?

然后我创建了root内容(id = 0content_table的内容。所有主要页面和部分都将root作为其父级。

我现在的问题是,我想在引用FOREIGN KEY列的parent_id上加rel_id。但是我要担心Root元素。我已经觉得我在paging_table的第一行做了一个黑客攻击。我现在感觉鸡肉和鸡蛋的情况根本内容。您是否认为根内容确实存在必要性?通用部分方法怎么样?我只是想要更好地设计这个数据库:),或者可能是CMS的体系结构的整体重新设计,因为我刚开始并且我还没有做太多。

非常欢迎批评(只是建设性的)。如果有任何含糊不清的内容,请发表评论,我会尽力将其清理干净,我只是很难清楚地表达我的想法,如果我只是向您发送源代码,那么这将是一件很麻烦的事情。建造。谢谢!

修改

我已经编辑了id以使参考清晰

3 个答案:

答案 0 :(得分:0)

让我亵渎神明:关系数据库不适合这种任务 - 建立层次关系显然很糟糕。我也犯过一次同样的错误,再也不会这样做了。我用文件系统作为存储和XML文档创建了小而轻的CMS。版本控制,复制,工作流等其他概念很容易上传 with(surprise !!!!) - 一些源版本控制系统,如git或svn。

另一种选择是面向文档的数据库,如MongoDB(还有其他的,但我现在最熟悉mongo) - 没有架构,简单的hiarachies,扩展得很好 - 你还需要什么? (并且有PHP驱动程序)

使用标准化数据来处理地狱;)

答案 1 :(得分:0)

您的部分现在指向内容记录,这很好。 但是,你需要摆脱尴尬的paging_table:

每个部分可以指向一个页面,并且有一个描述该父关系中“顺序”的整数。 如果Section不指向Page,它指向另一个Section,则可以重用“order”字段。

所以你有parent_page和parent_section字段,其中一个可能是NULL。如果你对规范化很疯狂,你需要更多的章节表,但你可能需要比你想象的更多。

请注意,您将丢失content_table中的层次结构信息,但这没关系,因为所有“内容”通常都没有层次结构。只有部分是层次结构的。

更简单的方法是将Page视为一种没有父节的Section。但我不太了解页面中可能涉及的其他数据。然而,在普通的Wiki中我会使用它。

修改: 如果您确实需要“重用”实际的Section记录,则需要一个SectionAssignment表,它允许Sections和Pages之间的m-n关系。 SectionAssignment将有四个字段:assignment_id,section_id,page_id和order。

答案 2 :(得分:0)

我真的没有看到问题。我只是将Root的parent_id留给Null:它没有父级,而且不是他自己的父级。
否则,SQL Server(可能还有其他一些RDBMS)有hierarchical capabilities