如何在数据库中实现完全不相交的专业化?

时间:2014-09-29 03:11:30

标签: sql database relational-database

假设有一个供学生和教授使用的数据库(非常简单),关系数据库如下:

GradStudent (_id_, name, gradStuff)
UndergradStudent (_id_, name, underGradStuff)
Professor (_id_, name)
Teaches(_prof_id_, _stud_id_)

考虑到上面的关系数据库是为了表示完全不相交的特化,即没有表Student而是两个完全独立的数据库,当在SQL中编写它以实现数据库时,我将如何获取Teaches表的学生ID? 我无法弄清楚如何从两个不同的表中创建一个外键。

我正在编写这个问题,假设SQL语言并非在所有平台上都有所不同。如果需要澄清:我正在开发Oracle SQL Developer。

修改 ::其他信息/澄清:

关于我想要实现的目标的更加图形化,简单化的观点:

我想在SQL代码中编写以下内容(但我不知道它是如何可能的,因此不知道如何)

enter image description here

如果图片太简单,我很抱歉,如果需要,我可以添加更多属性和详细信息,请告诉我。

2 个答案:

答案 0 :(得分:1)

如果通过“获取Teaches表的学生ID”,你的意思是你希望Teaches.stud_id是一个引用“GradStudent或Undergradstudent就是这种情况”的FK,你不能。 FK的目标必须是不是视图的表的键。你没有这样的桌子,你也没有这样的钥匙。

我唯一看到的方法就是编写一个触发器,对触发器进行插入/更新时进行检查。

答案 1 :(得分:1)

  

我无法弄清楚如何从两个不同的表中创建外键。

您的意思是,/引用两个不同表的外键。但是在这个设计中没有这样的外键。

我们为表声明一个SQL FOREIGN KEY(即告诉DBMS)列列表的值也是相应列(可能是同一列表)列表中值的唯一值表(也许是同一张表)。你这里没有这个。你的表有不同的约束。

如果您想要那些基表,那么您必须在SQL中使用触发器来强制执行约束。

您还可以使用以下设计:

  • 具有NOT NULL UNIQUE或PRIMARY KEY id的基表Student
  • 来自GradStudent(id),UndergradStudent(id)和Teaches(stud_id)的FOREIGN KEY REFERENCES学生(id)
  • 一个约束条件,即学生对id的投射是对于ID
  • 的GradStudent和UndergradStudent投影的不相交联合

您可以通过触发器表达后一个约束。表达脱节(但不是联盟)的无触发方式是:

  • GradStudent中的类型鉴别器/标签栏student_type(例如),UndergradStudent&学生在GradStudent和UndergradStudent中使用额外的FOREIGN(超级)KEY(id,student_type)到学生中的NOT NULL UNIQUE(id,student_type)
  • GradStudent CHECK(student_type ='grad')和UndergradStudent CHECK(student_type ='undergrad')

两个学生子类型基表中的每一个的行都是相同的(冗余),学生中的行由他们的id(冗余)确定,但这是没有触发器的情况下的成本。列student_type可以是计算列。

实际上没有很好的SQL方法来强制每个父ID都是一个孩子。仅具有上述子表的LEFT JOIN而不是父表和子表强制每个父项都是子项,但需要NULL列和进一步的约束。需要触发器来合理地约束SQL数据库。一个人使用成语来获得声明性约束。

有关子类型成语的更多信息,请参阅this answer and its links。谷歌'stackoverflow数据库sql表'加上子/父,超/子表,超/子类,继承和/或多态。还有多个/多个/两个FK /关系/关联/引用/链接(尽管通常在这个问题中需要的约束是一个FK,设计应该使用子类型)。我用Google搜索“stackoverflow两个外键”并得到this