为什么在SQL中为1:m关系建立连接表

时间:2009-08-11 23:14:19

标签: sql database one-to-many

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

alt text http://dl.getdropbox.com/u/175564/db/db-simple.png

本书 Joe Celko在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

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

3 个答案:

答案 0 :(得分:3)

嗯,独特的关系对我来说似乎没有意义,可能是因为我习惯于DBMS,你可以在其中定义除主键之外的唯一键。在我的世界中,像这样的映射表是如何实现多对多关系,并将它们用于一对多关系是疯狂的 - 我的意思是,如果你这样做,也许你打算对于要用作一对多的关系,但实际上实现的是多对多的支持。

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

答案 1 :(得分: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

如果您在那里有非唯一值,则数据库将阻止您插入或者如果您在答案中毫无疑问地插入数据库。您需要做的就是检查插入是否有效,仅此而已。您认为哪一个代码较少?

答案 2 :(得分:1)

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

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

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