0

在以下数据库中的第一个 1:m 和第二个 1:m 关系之间具有联结表有什么好处?

替代文字 http://dl.getdropbox.com/u/175564/db/db-simple.png

Joe Celko's trees and hierarchies in SQL for Smarties一书说,原因是在 1:m 中具有唯一的关系。例如,下表分别限制用户两次提出完全相同的问题和两次给出完全相同的答案。

第一个 1:m 关系

users-questions
===============
user_id REFERENCES users( user_id )
question_id REFERENCES questions ( question_id )
PK( user_id, question_id)           // User is not allowed to ask same question twice 

第二个 1:m 关系

questions-answers
=================
question_id REFERENCES questions( question_id)
answer_id REFERENCES answers( aswer_id )
PK( question_id, answer_id )       //  Question is not allowed to have to same answers

这种关于唯一性的好处并不能说服我让我的代码更具挑战性。我不明白为什么我应该限制在数据库中具有相同 ID 的问题或答案的可能性,因为我也许可以使用 PHP 来禁止它。

4

3 回答 3

3

好吧,唯一关系对我来说似乎很荒谬,可能是因为我习惯了 DBMS,您可以在其中定义除主键之外的唯一键。在我的世界里,像这样的映射表是你实现多对多关系的方式,而将它们用于一对多关系是疯狂的——我的意思是,如果你这样做,也许你打算让这种关系成为用作一对多,但您实际实现的是多对多支持。

我不同意您所说的持久层中没有唯一复合键的实用程序,因为您可以在应用程序层中强制执行它。持久层唯一性约束有很多难以复制的好处,例如,在 MySQL 中,能够利用INSERT ... ON DUPLICATE KEY UPDATE.

于 2009-08-11T23:21:34.613 回答
2

它通常是由于数据重复。

至于您的推理,是的,您可以在业务层执行此操作,但如果您犯了错误,可能会破坏大量代码。您遇到的问题是您的数据模型可能只有几个表。幸运的你。当您的数据模型增长时,如果您无法理解结构并且您必须将所有逻辑用于维护 GUI 层中的非规范化表,您很容易遇到问题。请注意,如果不使用会破坏性能的锁定,很难在 SQL 数据库的 GUI 上使事情成为线程安全的。

DBMS 非常擅长处理这些问题。您可以保持数据模型干净并使用索引为您提供所需的速度。你的目标应该是首先把它做好,并且只有在你明确需要这样做时才对表进行非规范化(为了性能等)

信不信由你,在许多情况下,标准化数据会让您的生活更轻松,而不是更难的应用程序。例如,如果您有一个包含问题和答案的大表,您必须编写代码来检查它是否是唯一的。如果您有一个带有主键的表,您只需编写

insert into table (col1, col2) values (@id, @value) --NOTE: You would probably 
--make the id column an autonumber so you dont have to worry about this

如果您在那里有一个非唯一值,或者如果您在没有问题的情况下放入答案,数据库将阻止您插入。您需要做的就是检查插入是否有效,仅此而已。你认为哪一个代码更少?

于 2009-08-11T23:36:32.710 回答
1

我同意在这种情况下一对多的连接表似乎并没有增加太多好处,正如@chaos 所说,你实际上最终实现了多对多支持。但乔·塞尔科是个聪明人——这真的是他给出的确切答案吗?

在一对多上实现连接表的另一个可能原因是它将问题/答案与对用户的依赖完全分开。

例如,假设您添加了一个Dogs表格和一个Deities表格。我们都知道狗不能注册为用户,因为它们没有电子邮件地址,而神也不会注册为用户,因为它在他们之下。也许狗和神仍然会问问题,但要做到这一点,您可能需要实现狗问题表和神灵问题表。从理论上讲,这仍然是多对多,但实际上您这样做是为了可以拥有多个一对多。

于 2009-08-11T23:44:23.803 回答