表cain加入两个表中的任何一个

时间:2013-01-07 19:04:14

标签: database-design

(我知道这可能是重复的,但我根据搜索找不到任何答案)

我有一张表格,其中包含一些可以加入用户或公司的信息。我有三种方法可以解决这个问题:

  1. 为表提供一个join_user_id列和一个join_company_id列,只填写其中一列。
  2. 创建一个join_id列和一个joins_with_table列
  3. 复制主表,以便有两个版本,一个只有一个join_user_id,另一个只有一个join_company_id。
  4. 我立即排除了3,因为它不干。我的问题是,哪些是真正规范化的设计(或者没有一个)?

    我如何处理以下缺点:  1.如果有第3张桌子,请留下一堆空箱,不会优雅地增长,我该如何简洁地加入?  2.如何强制执行外键约束?我如何简洁地加入?

3 个答案:

答案 0 :(得分:0)

不声称这是最佳做法,或者即使它适用于您的情况,但第四个选项可能是将usercompany表的列共用在一个单独的表中(也许{ {1}})。然后,用户和公司详细信息可以进入单独的user_comp_baseuser_details表,其中包含与company_details表中相同的密钥(可能还可以包含一个列,告知哪个表包含这一行)。

然后你只需要在表中使用user_company_base来解决外键约束和简洁连接的问题。当然,如果需要详细信息,则需要加入另一个表(join_id_user_comp_baseuser_details)。

编辑:我认为这个概念称为表继承。

答案 1 :(得分:0)

1或2都不是第三范式,因为在一列中设置值会告诉您有关另一列(不是主键)中的值的信息。这打破了完全依赖于3NF所需的主键的属性。

我肯定会排除选项2,因为创建外键会很棘手/不可能,并且可能会导致混淆列中值的含义。如果有人在不更改joins_with_table列的情况下更改join_id列,您可能不知道!

要在3NF中对此进行建模,您需要创建两个新表,一个用于用户,一个用于公司。这些将包含original_table_id, user_id(或公司),其中original_table_id为主键。然后,您需要验证一个表或另一个表中只有一个条目。

就我个人而言,我仍然会考虑在原始表格中将这些作为额外的列,但除非您认为您可能会添加更多表格,否则您需要有条件地参考。你不应该设计避免空值,所以我不担心这个。如果您需要返回此表中有关公司和用户的信息,则此解决方案和额外表方法都需要外部联接到usercompany表,因此查询复杂性没有真正的区别。 / p>

答案 2 :(得分:0)

  

其中哪些是真正规范化的设计(或者没有一个)?

所有这些都是“标准化的”,但并非所有这些都是同样有用的。

  

1)离开一堆空箱,不会优雅地成长。

大多数DBMS都可以非常有效地存储NULL。在理想情况下,通常只有一个字节,甚至只有一个DBMS上的一个字节。

您可以使用CHECK确保其中一个非NULL。

  

2)如何强制执行外键约束?

理论上,您可以将joins_with_table向下迁移到FK,然后在引用表中使用CHECK来确保正确的类型。显然,这很尴尬并浪费空间(除非DBMS支持计算/虚拟列)。

您可以依赖触发器或(上帝禁止)应用程序逻辑,但只要可能,声明性约束应该是首选,因为它们的简单性,健壮性和速度。

  

我立刻排除了3,因为它不干。

不幸的是,关系数据库通常不支持我们从OO编程中熟悉的概念,因此可能会遭受一些不必要的重复。例如,表继承(其中基表定义了“结构”,子节点定义了特定的FK)在这种情况下是减轻重复的理想选择。

实际上,只要你不要吹嘘不成比例,一些重复并不是世界上最糟糕的事情。

  

我如何简洁地加入?

我不确定我理解你的问题 - 请澄清一下。根据您的需要,JOIN不仅可以受到桌面设计的影响,还可以受key design的影响。


总而言之,我可能只是(1),除非你预见到其他可以保证的差异(3)。

相关问题