我有意见存储表格,注释可以来自其他用户或其他个人资料,其是在此应用程序独立的实体。数据库最佳实践
我原来的想法是,该表将同时拥有USER_ID和PROFILE_ID领域,因此,如果用户提交一个评论,它给USER_ID离开PROFILE_ID空白
这是正确的,错误的,有没有更好的办法?
我有意见存储表格,注释可以来自其他用户或其他个人资料,其是在此应用程序独立的实体。数据库最佳实践
我原来的想法是,该表将同时拥有USER_ID和PROFILE_ID领域,因此,如果用户提交一个评论,它给USER_ID离开PROFILE_ID空白
这是正确的,错误的,有没有更好的办法?
在过去,我已经使用了一个集中的意见表,有一个领域它引用的fk_table。
如:
comments(id,fk_id,fk_table,comment_text)
这样,你可以使用UNION查询,从不同的来源连接的数据。
SELECT c.comment_text FROM comment c JOIN user u ON u.id=c.fk_id WHERE c.fk_table="user"
UNION ALL
SELECT c.comment_text FROM comment c JOIN profile p ON p.id=c.fk_id WHERE c.fk_table="profile"
这确保您可以扩展具有评论的对象的数量而不会创建冗余表。
如果评论是一般性的几个对象,你可以创建一个表中的每个对象:
user_comments (user_id, comment_id)
profile_comments (profile_id, comment_id)
然后,你不必在你的意见表中的任何空列。它还可以使未来轻松添加新的评论源对象,而无需触摸评论表。
另一种方式来解决是始终非规范化(副本)上评论的留言者的姓名,还通过类型和id字段存储参考回到评议。这样你就有了一个统一的评论表,你可以快速搜索,排序和修剪。缺点是评论与其所有者之间没有任何真正的FK关系。
无论是最好的解决方案不仅仅取决于表更恕我直言,而且这是如何在应用程序中其他地方使用。
假设评论都与其他对象关联,可以说你提取该对象的所有意见。在您提出的设计中,提取所有评论需要从一个表中选择,这是有效的。但是,这是提取评论而不提取每条评论的海报信息。也许你不想展示它,或者它们已经被缓存在内存中。
但是,如果你不得不检索有关海报信息而获取的意见吗?然后你必须加入两个不同的表格,现在结果记录集会被很多NULL值所污染(对于配置文件注释,所有用户字段都将为NULL)。必须解析这个结果集的代码也可能变得更复杂。
就个人而言,我可能会用完全规范化的版本开始,然后非规范化当我开始看到性能问题
还有一个完全不同的可能解决问题的方法,但这取决于它是否使感觉在领域。如果在应用程序中还有其他地方可以交换使用者和海报,那该怎么办?如果用户只是一种特殊的配置文件会怎么样?然后我认为应该通常在用户/配置文件表中解决该解决方案。例如(简称一些伪SQL):
create table AbstractProfile (ID primary key, type) -- type can be 'user' or 'profile'
create table User(ProfileID primary key references AbstractProfile , ...)
create table Profile(ProfileID primary key references AbstractProfile , ...)
然后在你的应用程序,当用户或配置文件,可以交替使用,可以参考的登录ID的任何地方。
+1这是我开始写的解决方案。请参阅http://www.slideshare.net/billkarwin/practical-object-oriented-models-in-sql中的* Polymorphic Associations * – 2010-05-27 06:59:50
这里的另一种方法,它允许你保持通过外键参照完整性,集中管理,并使用标准的数据库工具如索引提供最高的性能,如果你真的需要,分区等:
create table actor_master_table(
type char(1) not null, /* e.g. 'u' or 'p' for user/profile */
id varchar(20) not null, /* e.g. 'someuser' or 'someprofile' */
primary key(type, id)
);
create table user(
type char(1) not null,
id varchar(20) not null,
...
check (id = 'u'),
foreign key (type, id) references actor_master_table(type, id)
);
create table profile(
type char(1) not null,
id varchar(20) not null,
...
check (id = 'p'),
foreign key (type, id) references actor_master_table(type, id)
);
create table comment(
creator_type char(1) not null,
creator_id varchar(20) not null,
comment text not null,
foreign key(creator_type, creator_id) references actor_master_table(type, id)
);
+ 1为正确的规范化技术 – DancesWithBamboo 2010-05-27 06:23:41
我喜欢这个解决方案,但对评论者或评论者类型的评论做一个简单的过滤将需要一个连接。 – cherouvim 2010-05-27 06:33:41
的确如此 - 但是一个连接是一个小缺点,并且总是可以为此创建一个View或Stored Procedure,因此每次需要获取该数据时都不必考虑连接。 – becquerel 2010-05-27 06:49:16