Php 我应该为用户个人地址和用户组地址设置1个或2个表吗?

Php 我应该为用户个人地址和用户组地址设置1个或2个表吗?,php,mysql,database,database-design,doctrine,Php,Mysql,Database,Database Design,Doctrine,如果我有用户,以及像本地天文组/俱乐部这样的用户组,并且我希望两者都与街道地址有一对多的关系,那么我可以只拥有一个地址表和两个fk,这样我就不必复制表模式吗?还是最好只使用两个单独的表,即用户地址和用户组地址?感谢您的投入和时间,谢谢 如果用户和组的地址实际上是同一类型的地址,那么您可以根据需要使用一个地址表进行引用。最好使用一个地址表,除非一个地址类型比另一个地址类型有特殊需要。这更易于维护,还允许您添加功能。例如,如果您当地的天文学团体决定在某处举办活动,那么您只需创建活动表并引用地址表即可

如果我有用户,以及像本地天文组/俱乐部这样的用户组,并且我希望两者都与街道地址有一对多的关系,那么我可以只拥有一个地址表和两个fk,这样我就不必复制表模式吗?还是最好只使用两个单独的表,即用户地址和用户组地址?感谢您的投入和时间,谢谢

如果用户和组的地址实际上是同一类型的地址,那么您可以根据需要使用一个地址表进行引用。

最好使用一个地址表,除非一个地址类型比另一个地址类型有特殊需要。这更易于维护,还允许您添加功能。例如,如果您当地的天文学团体决定在某处举办活动,那么您只需创建活动表并引用地址表即可。如果您将它们拆分,那么每次您有一个具有地址的新实体时,您都必须创建一个新表

希望这有帮助


至于你的评论:我会把参考放在一个单独的参考表中

您描述的带有两个外键的设计称为独占弧。只能填充两个外键中的一个。执行和使用起来都很尴尬

例如,一个地址必须引用一个实体,因此从概念上讲,该列是必需的,不应为NULL。但不能使两列都不为NULL,因为其中一列不属于给定的地址。所以它们必须是可空的。然后你必须有一些其他的方法来防止两者都为NULL,也防止两者都为非NULL。MySQL不支持检查约束,所以您可以编写触发器或编写自定义应用程序代码来强制执行此规则

创建一个地址表,但颠倒关系如何?也就是说,Users和Groups表包含对Addresses表的外键引用,而不是相反

另一种解决方案是让用户和组都依赖于一个公共的超表,称之为可寻址表或其他什么。类似于面向对象设计中的接口或抽象类。然后,您的地址也可以有一个可寻址的外键。请参见中的示例


在我的书《多态关联》一章中,我还更详细地讨论了这个问题。

数据库设计的首要任务是有效性。当使用一个表策略来持久化所有地址时,将有一个隐式定义,说明地址是属于用户还是属于组

因为您不必识别所需的setusers或group是哪个地址,所以双表策略是一种更简单的编程方法,可以防止有人编写错误的codeSQL

例如,我们需要一些来自用户地址的数据:

SELECT * FROM user_address WHERE <other conditions>; // The two-table strategy

/**
 * The one-table strategy
 */
SELECT * FROM all_addresses
WHERE user_id IS NOT NULL
    AND <other conditions>;
此外,如果我们使用两个表来持久化所需的地址,那么性能会更好

在一种表策略中,可能不会优化IS NOT NULL条件,即使该列中有索引,这取决于数据库系统。Join是在一种表策略中识别用户地址的另一种方法,但它仍然比另一种策略更费力

然而,单表策略有其性能优势。如果我们需要收集所有的地址,不管是用户还是组,这种操作就是性能
系统的瓶颈,你可以考虑使用一个表策略。< /P>有2个FK,或者对于每一个需要与地址有一对多关系的其他对象有可能是FK吗?还是我应该使用一个参考表?@blacktie24:就像NullRef一样,我也在考虑一个参考表。但是也可以只使用外键。这取决于你想走多远。例如,如果您添加更多应该引用地址的表,我会选择引用表。明白了,是的,我计划继续使用引用表。你能看看底部@Mike Lue的答案吗?你能看看我在@hakre的另一个答案中的评论吗?@blacktie24我修改了我的答案。当我对@hakre发表评论时,这是有意义的,我计划使用参考表。不过,你也可以看看@Mike Lue的答案吗?@blacktie24:也检查一下Bill Karwin的答案;-我不是一个专业的DBA,但看起来他有很多信息要分享。是的,我想一开始我担心像我这样的外行不会理解他的帖子,但他的帖子写得真的很好!为了澄清,我希望在用户/组和地址之间建立一对多关系,因此我不能在用户/组内设置fk。但是,在阅读了以下线程中的响应之后,我觉得最干净、最简单的选项是选项1:为每个目标创建一个额外的表。但最终,我还是不知道
了解您列出的3个选项中的每一个的区别。在这一点上是偏好吗?你也可以在这个帖子中查看@Mike Lue的答案吗?这是我最初想到的解决方案之一,但由于冗余的表结构,它似乎效率低下,可能是一个维护问题?@blacktie24:我认为@Mike Lue的答案很好。将数据拆分为两个表实际上效率更高。索引数据结构不太深,等等。如果一种类型的地址具有一些不属于另一种类型的自定义属性,则可以使两个表不同。