在表设备中,我有一个类型,如果类型是加热器,则与加热器表建立关系,否则,如果类型是灯,则与灯表建立关系。这样的事情有可能做到吗?

@MikeNakis,所以这应该是不可能的:
Device table:
+-----+----------+----------+
| Id | LampId | HeaterId |
+-----+----------+----------+
| 1 | NULL | 1 |
| 2 | 2 | 2 |
| 3 | 3 | NULL |
| 4 | NULL | 4 |
+-----+----------+----------+
Lamp table:
+-----+----
| Id |
+-----+----
| 2 |
| 3 |
+-----+----
Heater table:
+-----+----
| Id |
+-----+----
| 1 |
| 2 |
| 4 |
+-----+----发布于 2020-03-23 17:38:09
是的,这是可以做到的。
这是对象关系映射(ORM)框架的工作方式之一(在我看来是最好的方式)。这不是巧合,因为您在这里尝试实现的是映射到关系数据库的面向对象的继承层次结构。“设备”是基类,而“灯”和“加热器”是派生(后代)类。
下面是如何做的:
删除Type列。正如我将进一步展示的那样,它将成为一个计算列。
引入两个所谓的“Type -id”列,而不是后代列:一个HeaterId列和一个LampId列。如果您愿意,可以添加一个约束,即只允许这些后代id列中的一个为非空。如果以后添加更多的设备,则必须添加更多的子代id列。
然后,您可以使Type成为计算列,基于哪个后代id列包含非空值。
坏消息是,您将无法设置Type列的值,但这没有关系;您将通过将一个非null值存储到一个后代id列中来隐式定义类型,而不是设置Type。
注意:在面向对象编程中,很少会设计一个基类来让它了解它的后代。有些人甚至会说,拥有这样的知识是荒谬的。我不会这么绝对,我遇到过一些小的、紧密结合的、不可扩展的类图的例子,在这些例子中,这样的知识是合法的和有用的。但在任何情况下,即使您严格遵守基类永远不应该知道其后代的格言,这也不完全是面向对象的编程:这是关系数据库设计。这是为了将类图映射到数据库而必须付出的代价。
进一步澄清:
首先,一些术语:“长行”是一对父行(基行/祖先行)加上子行,一起检查。“行片段”只是其中之一,需要单独检查。
每个子代行片段必须与其父行片段具有完全相同的主键id。因此,下面是一个示例结构:
Device table:
+-----+----------+----------+
| Id | LampId | HeaterId |
+-----+----------+----------+
| 1 | NULL | 1 |
| 2 | 2 | NULL |
| 3 | 3 | NULL |
| 4 | NULL | 4 |
+-----+----------+----------+
Lamp table:
+-----+----
| Id |
+-----+----
| 2 |
| 3 |
+-----+----
Heater table:
+-----+----
| Id |
+-----+----
| 1 |
| 4 |
+-----+----这意味着在基行片段中,一个不为空的后代id始终具有与同一行的主键完全相同的值。
这种方式除了非常容易排除故障外,还有一个额外的性能优势:将整个长行插入到数据库中不需要到数据库的任何额外往返:使用序列或自动增量值只发出一个id,并且这是参与插入的所有行片段唯一需要的id。即使您的继承层次结构比两个级别更深,这也是一种魅力。
https://stackoverflow.com/questions/60809991
复制相似问题