有关评论的澄清:
>这是手动维护,而不是通过ORM包.
>这涉及的项目位于sql Server之上(但是看到通用解决方案会很高兴)
>这可能不是最好的例子.关于子类化我们可以考虑几种情况,我刚刚发明了这个学生/运动员的例子.
A)以真正的面向对象的方式,超类可以自己存在,不需要在任何子类中建模.
B)在现实生活中,任何对象或学生都可以有多个角色.
C)我试图说明的特定场景要求每个对象只在一个子类中实现.可以将超类视为一个抽象实现,或者只考虑其他不同的对象类/实例中的共性.
感谢大家的投入,特别是比尔.
解决方法
CREATE TABLE athletes ( student_id INT NOT NULL PRIMARY KEY,FOREIGN KEY (student_id) REFERENCES students(student_id),CHECK (student_id NOT IN (SELECT student_id FROM musicians UNION SELECT student_id FROM slackers UNION ...)) );
编辑:@JackPDouglas正确地指出Microsoft sql Server不支持上述形式的CHECK约束.事实上,根据sql-99标准,引用另一个表也是有效的(见http://kb.askmonty.org/v/constraint_type-check-constraint).
sql-99为多表约束定义元数据对象.这称为ASSERTION,但我不知道任何实现断言的RDBMS.
可能更好的方法是使student表中的主键成为复合主键,第二列表示子类型.然后将每个子表中的该列限制为与表所表示的子类型对应的单个值.编辑:不需要将PK作为子表中的复合键.
CREATE TABLE athletes ( student_id INT NOT NULL PRIMARY KEY,student_type CHAR(4) NOT NULL CHECK (student_type = 'ATHL'),FOREIGN KEY (student_id,student_type) REFERENCES students(student_id,student_type) );
当然,student_type可以很容易地成为整数,我只是将它显示为char用于说明目的.
如果您不支持CHECK约束(例如MysqL),那么您可以在触发器中执行类似的操作.
我阅读了关于确保超类表中每一行的某些子类表中存在一行的后续操作.我认为有一种实用的方法可以用sql元数据和约束来做到这一点.我建议满足此要求的唯一选择是使用Single-Table Inheritance.否则,您需要依赖应用程序代码来强制执行它.
编辑:JackPDouglas还建议使用基于Class Table Inheritance的设计.参见his example或类似技术here或here或here的示例.