0

(我知道这可能是重复的,但我无法通过搜索找到任何答案)

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

  1. 给表一个 join_user_id 列和一个 join_company_id 列,并且只填写两者之一。
  2. 创建一个 join_id 列和一个 joins_with_table 列
  3. 复制主表,以便有两个版本,一个只有一个 join_user_id,一个只有一个 join_company_id。

我立即排除 3,因为它不干。我的问题是,其中哪一个是真正的规范化设计(或者都不是)?

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

4

3 回答 3

0

不声称这是最佳实践,或者即使它适用于您的情况,但第四个选项可能是将共同的列usercompany表保留在单独的表中(也许user_comp_base)。user_details然后,用户和公司详细信息可以使用与company_details表中相同的键进入单独的user_company_base表(该表可能还包含一个列,告诉哪个表包含该行的详细信息)。

然后你只需要join_id_user_comp_base在你的表中解决外键约束和简洁连接的问题。当然,如果需要详细信息,这是以加入另一个表 ( user_detailsOR )为代价的。comp_details

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

于 2013-01-07T19:16:27.917 回答
0

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

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

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

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

于 2013-01-07T20:26:09.400 回答
0

其中哪一个是真正的规范化设计(或都不是)?

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

1)留下一堆空洞,不会优雅地成长。

大多数 DBMS 相当有效地存储 NULL。通常是一个字节,在理想情况下,在某些 DBMS 上甚至只有一个位。

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

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

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

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

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

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

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

如何简洁地加入?

我不确定我是否理解您的问题-请澄清。根据您的需要,JOIN 不仅会受到表设计的极大影响,还会受到键设计的影响。


总而言之,我可能会选择(1),除非您预计其他可能需要(3)的差异。

于 2013-01-09T00:29:59.460 回答