(我知道这可能是重复的,但我根据搜索找不到任何答案)
我有一张表格,其中包含一些可以加入用户或公司的信息。我有三种方法可以解决这个问题:
我立即排除了3,因为它不干。我的问题是,哪些是真正规范化的设计(或者没有一个)?
我如何处理以下缺点: 1.如果有第3张桌子,请留下一堆空箱,不会优雅地增长,我该如何简洁地加入? 2.如何强制执行外键约束?我如何简洁地加入?
答案 0 :(得分:0)
不声称这是最佳做法,或者即使它适用于您的情况,但第四个选项可能是将user
和company
表的列共用在一个单独的表中(也许{ {1}})。然后,用户和公司详细信息可以进入单独的user_comp_base
和user_details
表,其中包含与company_details
表中相同的密钥(可能还可以包含一个列,告知哪个表包含这一行)。
然后你只需要在表中使用user_company_base
来解决外键约束和简洁连接的问题。当然,如果需要详细信息,则需要加入另一个表(join_id_user_comp_base
或user_details
)。
编辑:我认为这个概念称为表继承。
答案 1 :(得分:0)
1或2都不是第三范式,因为在一列中设置值会告诉您有关另一列(不是主键)中的值的信息。这打破了完全依赖于3NF所需的主键的属性。
我肯定会排除选项2,因为创建外键会很棘手/不可能,并且可能会导致混淆列中值的含义。如果有人在不更改joins_with_table
列的情况下更改join_id
列,您可能不知道!
要在3NF中对此进行建模,您需要创建两个新表,一个用于用户,一个用于公司。这些将包含original_table_id, user_id
(或公司),其中original_table_id
为主键。然后,您需要验证一个表或另一个表中只有一个条目。
就我个人而言,我仍然会考虑在原始表格中将这些作为额外的列,但除非您认为您可能会添加更多表格,否则您需要有条件地参考。你不应该设计避免空值,所以我不担心这个。如果您需要返回此表中有关公司和用户的信息,则此解决方案和额外表方法都需要外部联接到user
和company
表,因此查询复杂性没有真正的区别。 / p>
答案 2 :(得分:0)
其中哪些是真正规范化的设计(或者没有一个)?
所有这些都是“标准化的”,但并非所有这些都是同样有用的。
1)离开一堆空箱,不会优雅地成长。
大多数DBMS都可以非常有效地存储NULL。在理想情况下,通常只有一个字节,甚至只有一个DBMS上的一个字节。
您可以使用CHECK确保其中一个非NULL。
2)如何强制执行外键约束?
理论上,您可以将joins_with_table
向下迁移到FK,然后在引用表中使用CHECK来确保正确的类型。显然,这很尴尬并浪费空间(除非DBMS支持计算/虚拟列)。
您可以依赖触发器或(上帝禁止)应用程序逻辑,但只要可能,声明性约束应该是首选,因为它们的简单性,健壮性和速度。
我立刻排除了3,因为它不干。
不幸的是,关系数据库通常不支持我们从OO编程中熟悉的概念,因此可能会遭受一些不必要的重复。例如,表继承(其中基表定义了“结构”,子节点定义了特定的FK)在这种情况下是减轻重复的理想选择。
实际上,只要你不要吹嘘不成比例,一些重复并不是世界上最糟糕的事情。
我如何简洁地加入?
我不确定我理解你的问题 - 请澄清一下。根据您的需要,JOIN不仅可以受到桌面设计的影响,还可以受key design的影响。
总而言之,我可能只是(1),除非你预见到其他可以保证的差异(3)。