我有一个带有uniqueidentifier的列,它可能会引用四个不同表中的一个。我已经从两个方面看到了这一点,但两者看起来都是不好的做法。
首先,我看过一个ObjectID列而没有明确地将其声明为特定表的外键。然后你可以推送你想要的任何uniqueidentifier。这意味着您可能会从不属于我想要的4个表的表中插入ID。
其次,因为数据可能来自四个不同的表,我也看到人们制作了4个不同的外键。在这样做时,系统依赖于ONE AND ONLY ONE列具有非NULL值。
这样做有什么好办法?例如,我的表中的记录可能会引用医院(ID),诊所(ID),学校(ID)或大学(ID)......但仅限于那些表格。
谢谢!
答案 0 :(得分:6)
您可能需要考虑Type / SubType数据模型。这与面向对象编程中的类/子类非常相似,但实现起来更加笨拙,并且没有RDBMS(我知道)本身支持它们。一般的想法是:
你注意到这个模型的问题,对吗?什么是让建筑物在两个或多个子类型表中都有条目?很高兴你问:
Voila:给定一个类型为H的BUILDING行,不能将SCHOOL表中的条目(类型S)设置为引用该构建
你会记得我确实说它很难实现。
事实上,最大的问题是:这值得吗?如果有意义的是将四种(或更多,如时间)建筑类型实现为类型/子类型(进一步的规范化优势:一个地址用于地址和每个建筑物共有的其他属性,特定于建筑物的属性存储在子表中),构建和维护可能值得付出额外的努力。如果没有,那么你又回到原点:一个在现代普通RDBMS中难以实现的逻辑模型。
答案 1 :(得分:4)
让我们从概念层面开始吧。如果我们将医院,诊所,学校和大学视为主题实体的类别,是否有超类可以概括所有这些实体?可能有。我不打算告诉你它是什么,因为我不像你那样理解你的主题。但是,我将继续进行,好像我们可以将所有这些称为“机构”,并将四者中的每一个视为机构的子类。
正如其他响应者所指出的,类/子类扩展和继承并未构建到大多数关系数据库系统中。但是如果你知道正确的流行语,那就有很多帮助。以下内容旨在教您数据库术语中的流行语。以下是流行语的摘要:“ER Generalization”,“ER Specialization”,“Single Table Inheritance”,“Class Table Inheritance”,“Shared Primary Key”。
保持概念层面,ER建模是在概念层面理解数据的好方法。在ER建模中,有一个概念,“ER概括”和一个对应的概念“ER专业化”,它将我刚才提出的思想过程与“超类/子类”相提并论。 ER Specialization告诉您如何绘制子类图,但它没有告诉您如何实现它们。
接下来,我们从概念级别向下移动到逻辑级别。我们用关系来表达数据,或者,如果你愿意,我们用SQL表来表达数据。有几种实现子类的技术。一种称为“单表继承”。另一种称为“类表继承”。与Class表继承相关,还有另一种名为“Shared primary Key”的技术。
在您继续使用类表继承的情况下,我们首先设计一个名为“INSTIT”的表,其中包含Id字段,名称字段以及与机构相关的所有字段,无论它们属于哪四种是。比如邮寄地址字段之类的东西。同样,您比我更了解您的数据,并且您可以找到所有四个现有表中的字段。我们以通常的方式填充id字段。
接下来,我们设计了四个名为“医院”,“诊所”,“学校”和“大学”的表格。这些将包含一个id字段,以及仅属于该类机构的所有数据字段。例如,医院可能具有“床位”。同样,您比我更了解您的数据,并且您可以从现有表中的字段中找出这些数据,而这些字段并未进入“机构”表。
这就是“共享主键”的用武之地。当一个新条目进入“机构”时,我们必须在四个专用子类表之一中创建一个新的并行条目。但是我们不使用某种自动编号功能来填充id字段。相反,我们将“INSTIT”表中的id字段的副本放入子类表的id字段中。
这是一项小工作,但这些好处值得付出努力。共享主键强制实施子类条目和超类条目之间关系的一对一性质。它使加入超类数据和子类数据变得简单,容易和快速。它不需要特殊字段来告诉您给定机构属于哪个子类。
而且,在您的情况下,它为您的原始问题提供了方便的答案。您最初询问的外键现在始终是INSTIT表的外键。而且,由于shared-primary-key的神奇之处,外键还引用了相应子类表中的条目,没有额外的工作。
为方便起见,您可以创建四个视图,将机构数据与四个子类表中的每一个组合在一起。
在Web上查找“ER专业化”,“类表继承”,“共享主键”以及“单表继承”,并在此处查找。 SO中有大多数这些概念或技术的标签。
答案 2 :(得分:0)
您可以在表上放置一个触发器并在那里强制执行引用完整性。我认为实现这一要求并不是一个非常好的开箱即用功能。