2

我有一个作为通用超类的电子设备表,然后为电话、笔记本电脑、相机等分开子类表,这些表扩展了超类并提供了有关设备的特定信息(使用超类表中的外键 deviceID),换句话说,类表继承。我的问题是,我应该在超类中有一个“deviceType”列吗?这将是多余的,因为您可以通过查看特定 deviceID 出现在哪个子类表中来发现设备类型,但这似乎是不必要的连接数量来找出如此简单的东西。

一般来说,一个人看到一个随机的通用设备并想知道它是什么类型可能是不寻常的,但将设计留在那个人很难轻易发现的地方似乎也很奇怪。

另一个问题是约束......我如何约束它以使设备仅被子类型化一次?例如,如何阻止将具有相同设备 ID 的行添加到膝上型计算机表中,因为该行与 Camera 表中已经存在的行相同?同样,这在良好的 UI 中是不可能实现的,但数据库约束总是更可取的。

谢谢!

PS 如果我们确实使用 deviceType 列,为了帮助数据完整性,它将链接到我们支持的所有设备类型的枚举表,而不是自由文本字段。

为澄清而添加


首先是超类表:

通用设备

deviceID    brand     shipDate
   1        HP        05/06/09
   2        Canon     11/16/08
   3        Ikon      02/27/09

这里有两个示例子类:

笔记本电脑

laptopID    deviceID    screenSize
   1           1           17

相机

cameraID      deviceID     megapixels
   1             2            6.5
   2             3            8

请注意 GenericDevice 表中“deviceID”的迁移键。这允许从通用表到任何子类表的一对一关系,具体取决于它实际上是什么类型的设备。因此,您可以加入这些表格来查看 HP 设备是一台 17 英寸屏幕的笔记本电脑,而佳能和 Ikon 设备都是分别具有 6.5 和 8 兆像素的相机。

问题是如果你一开始不知道设备是什么类型,而你所拥有的只是 GenericDevice 表中的一行。我们以第一行为例。您知道该设备由 HP 制造并于 2009 年 5 月 6 日发货,但您最初并不知道它是什么类型的设备。但是您可以通过搜索子表来找出它,直到找到 deviceID = 1 的行。笔记本电脑表包含这样一行,因此 HP 设备实际上必须是那台笔记本电脑。但这似乎是简单地发现设备类型的不必要麻烦(特别是如果您必须搜索 20 多个子类以查看 deviceID 匹配的位置)。相反,您可以这样做:

通用设备

deviceID    brand     shipDate   deviceType
   1        HP        05/06/09      laptop
   2        Canon     11/16/08      camera
   3        Ikon      02/27/09      camera

现在您可以立即查看 HP 设备的类型。但是现在你有重复的数据(隐式)。要了解原因,请考虑用户是否进行了此更改:

通用设备

deviceID    brand     shipDate   deviceType
   1        HP        05/06/09      camera
   2        Canon     11/16/08      camera
   3        Ikon      02/27/09      camera

(第一行的 deviceType 已切换为相机)
现在您的信息存在冲突 - 上表表明 HP 设备是相机,但在笔记本电脑表中有一行设备。换句话说,您实际上将 HP 设备的类型存储了两次。一次使用 GenericDevice 表中的 deviceType 字段,一次简单地因为膝上型计算机表中有一行 deviceID = 1。

4

3 回答 3

2

只将类型存储在一个表中,父或子,只需选择一个。如果你把它保存在两个地方,你必须让它们保持同步,为什么不把所有的孩子信息都保存在父母身上呢?这使它更容易;-)(开个玩笑,不要把所有东西都放在父表中!)

编辑

我会将 Type 列放入 GenericDevice 表中,但我会将其设置为代码或数字 ID 和 DeviceType 表的 FK,而不是像“笔记本电脑”或“相机”这样的词。还要确保品牌在品牌表中使用代码或 ID 和 FK。

GenericDevice
deviceID    brand     shipDate   deviceType 
1           1         05/06/09   L
2           2         11/16/08   C
3           3         02/27/09   C

DeviceTypes
deviceType   deviceDescription
L            Laptop
C            camera

Brands
BrandID   BrandName
1         HP
2         Canon
3         Ikon

根据不同值的预期数量选择您的代码/ID 数据类型。

对于它的价值,您可以像这样查询(不使用 deviceType 列):

SELECT
    g.deviceID,g.shipDate
        ,l.screenSize
        ,c.megapixels
    FROM GenericDevice          g
        LEFT OUTER JOIN Laptop  l ON g.deviceID=l.deviceID
        LEFT OUTER JOIN Camera  c ON g.deviceID=c.deviceID
    WHERE g.deviceID=1234
于 2009-07-06T18:45:35.413 回答
1

“但这似乎是为了找出如此简单的东西而进行的不必要的连接。”

你说对了。

我一直站在你的立场上,幸运的是,我仍然为这个网站添加了书签,以防我需要再次引用它。它甚至包括有关如何设置您正在寻找的约束的信息。

假设您使用的是 SQL Server,请执行以下操作: 在 SQL Server 中实现表继承

于 2009-07-06T20:30:46.183 回答
0

我会在父表中维护一个 deviceType 列,因为您可能有多个设备类型映射到同一个子表。

我会在任何实际需要它来加速查询的子表中维护一个 deviceType 的副本。我不会假设仅仅为了获得 deviceType 而加入父母会真的减慢速度。此外,您可能最终会使用父表中的许多列,在这种情况下,再多一列不会有任何损害。

副本将由插入和更新触发器维护。


您提到了更新 deviceType 导致数据完整性问题的问题。答案是“不要那样做”。如果设备类型不能改变,那么更新触发器应该根本不允许改变。

于 2009-07-06T18:43:57.820 回答