父子设计可轻松识别子类型

时间:2017-01-30 17:06:01

标签: database oracle database-design

在我们的数据库设计中,我们有几个描述不同对象但具有相同基本类型的表。由于描述实际的表以及每个列正在做什么将需要很长时间,我将尝试通过使用基于作业数据库的类似结构化示例来简化它。

所以说我们有以下表格:

enter image description here

这些表彼此之间没有连接,但共享相同的列。所以第一步是统一相同的列并引入一个独特的personId:

enter image description here

现在我们有#34;标题"然后使用personId PK作为FK,使用1对1关系链接到更具体的作业表的人员列。在我们的用例中,一个人只能拥有一份工作,因此personId在Taxi驱动程序,程序员和建筑工人表中也是唯一的。

虽然这个结构有效,但我们现在有了一个用例,在我们的应用程序中,我们得到了personId,并希望得到相应作业表的数据。这让我们遇到了一个问题,即我们无法立即知道这个人正在做什么样的工作。

我们提出了一些解决此问题的方案:

在后端处理它

这意味着只需保留架构,并在后端代码中查找正确的表。这可能意味着查看存在的每个表和/或构造一个半复杂的连接选择,我们必须筛选所有列以找到填充的那些。

总而言之:可能但意味着许多不必要的选择。我们还希望在实际数据库中保留这种面向数据库的逻辑。

使用类型字段

这意味着在Person表中添加一个字段列,例如用数字填充,以确定正确的子表,如:

enter image description here

所以你可以在Type中加一个0,如果它是一个出租车司机,如果它是一个程序员就可以加1等等......

虽然这大大减少了后端逻辑的数量,但我们必须确保我们在Type字段中使用的数字在后端是已知的,并且不会发生变化。

为每个表使用单独的ID

这意味着每个作业都在Person中获得自己的ID(必须可以为空),如:

enter image description here

现在很容易找出每个人的工作由于其他人有空ID。

所以我的问题是:这些设计中哪一个是最佳实践?我在这里错过了一个明显的解决方案吗?

3 个答案:

答案 0 :(得分:1)

Bill Karwin对类似这个问题做了很好的解释。 https://stackoverflow.com/a/695860/7451039

答案 1 :(得分:0)

我们现在决定选择第二个选项,因为它似乎带有其他评论者和海报所描述的最少的弊端。由于没有实际的答案描述第二个选项作为解决方案,我将尝试总结我们的推理:

针对选项1:

无法区分类型与查看父表。因此,后端必须包括所有逻辑,包括扫描包含id的所有表。虽然你可以将大多数逻辑压缩成一个大的连接选择,但与其他选项相比,它仍然会有更多的逻辑。

反对选项3:

正如@ yuri-g所说,这个技术上是不可能的,因为单独的ID无法设置为主键。它们必须是可空的,因此无法编入索引,实质上使父表无用,因为其中一个原因就是在表中有一个唯一的personID。

针对包含所有列的单个表:

对于我在问题中描述的小用例,这可能是我可行的,但我们讨论的是一堆表,每个表大约有2-6列。这会使这个选项很快变成一个混乱的列。

针对具有键值表的扁平设计:

我们的属性具有完全不同的数据类型,不同的约束和外键关系。在这种设计中,所有这些都是不可能/困难的。

针对自定义数据库对象包含子特定属性:

虽然@Matthew McPeak提出的这个选项对很多人来说可能是一个可行的选择,但我们的数据库设计从未真正使用过对象,因此将它们引入混合可能会引起混淆,而不是帮助我们。

赞成第二种选择:

这个选项在我们面向表的数据库结构中很容易使用,可以很容易地区分正确的子表,并且不需要进行大量的返工。特别是因为我们已经有类似于Type表的东西,我们可以很容易地将它用于此目的。

答案 2 :(得分:-1)

第三种选择,正如你所描述的那样,是不可能的:没有RDBMS(至少,我个人知道)会允许你在PK中使用NULL(甚至复合)。

第二是现实的。

是的,首先需要N个查询来轮询亲戚以确定实际类型(其中N是类型的数量)。 虽然你不会在第二种情况下使用一个查询逃脱:总会有两个查询,因为你不能加入,除非你知道你应该加入什么。

所以基本上你的设计存在缺陷,你应该考虑其他选择。 就像,非规范化一样:无论如何将非共享属性划分到父表中,然后字段对于非相应类型变为空值。 或者通过主键相关的灵活,平坦的属性 - 值对列表(是的,架构实施是权衡)。

或切换到面向列的DB:就是这种情况。