sql – 在关系数据库中维护子类完整性

前端之家收集整理的这篇文章主要介绍了sql – 在关系数据库中维护子类完整性前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
假设我有一张表代表超级班的学生.然后我有N个表格代表该对象的子类(运动员,音乐家等).如何表达约束,使学生必须在一个(不多于,不少于)子类中建模?

有关评论的澄清:

>这是手动维护,而不是通过ORM包.
>这涉及的项目位于sql Server之上(但是看到通用解决方案会很高兴)
>这可能不是最好的例子.关于子类化我们可以考虑几种情况,我刚刚发明了这个学生/运动员的例子.

A)以真正的面向对象的方式,超类可以自己存在,不需要在任何子类中建模.

B)在现实生活中,任何对象或学生都可以有多个角色.

C)我试图说明的特定场景要求每个对象只在一个子类中实现.可以将超类视为一个抽象实现,或者只考虑其他不同的对象类/实例中的共性.

感谢大家的投入,特别是比尔.

解决方法

这里有几种可能性.一个是每个表中的CHECK,其中student_id没有出现在任何其他姐妹子类型表中.这可能很昂贵,每次需要新的子类型时,都需要修改所有现有表中的约束.
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或类似技术hereherehere的示例.

原文链接:https://www.f2er.com/mssql/83724.html

猜你在找的MsSQL相关文章