4.4.7 复杂check条件与断言
复杂check条件
本节描述SQL
标准所支持的另外一些用于声明完整性约束的结构。然而,读者应该注意的是,这结构目前还没有被大多数数据库系统支持。
正如SQL
标准所定义的, check
子句中的谓词可以是包含子查询的任意谓词。如果一个数据库实现支持在check
子句中出现子查询,我们就可以在关系section
上声明如下所示的参照完整性约束:
1 | check( time_slot_id in( select time_slot_id from time_slot )) |
这个check
条件检测在section
关系中每个元组的time_slot_id
的确是在time_slot
关系中某个时间段的标识。
因此这个条件不仅在section
中插入或修改元组时需要检测,而且在time_slot
关系改变时也需要检测(如在time_slot
关系中,当一个元组被删除或修改的情况下)。
在我们的大学模式上,另一个自然的约束是:每个课程段都需要有至少一位教师来讲授。
为了强制实现此约束,一种方案是声明section
关系的属性集(course_d,seed, semester,yea)
为外码,它参照teaches
关系中的相应属性。遗憾的是,这些属性并未构成teaches
关系的主码。如果数据库系统支持在check
约束中出现子查询的话,可以使用与time_slot
属性类似的check
约束来强制实现上述约束。
复杂check
条件在我们希望确保数据完整性的时候是很有用的,但其检测开销可能会很大
。例如check
子句中的谓词不仅需要在section
关系发生更新时计算,而且也可能在time_slot
关系发生更新时检测,因为time_slot
在子查询中被引用了。
断言
一个断言(assertion
)就是一个谓词,是一种命名约束,它表达了数据库状态必须满足的逻辑条件域约束
和参照完整性约束
是断言的特殊形式
。
断言 示例
我们前面用大量篇幅介绍了这几种形式的断言,是因为它们容易检测并且适用于很多数据库应用。但是,还有许多约束不能仅用这几种特殊形式来表达。如有两个这样的例子:
- 对于
student
关系中的每个元组,它在属性tot_cred
上的取值必须等于该生所成功修完课程的学分总和。 - 每位教师不能在同一个学期的同一个时间段在两个不同的教室授课。
SQL
中的断言为如下形式:
1 | create assertion <assertion-name> <check predicate>; |
第一个断言 实现
1 | create assertion credits_earned_constraint check( |
只有不破坏断言的数据库修改才被允许
当创建断言时,系统要检测其有效性。如果断言有效,则今后只有不破坏断言的数据库修改才被允许。如果断言较复杂,则检测会带来相当大的开销。因此,使用断言应该特别小心。
由于检测和维护断言的开销较大,一些系统开发者省去了对一般性断言的支持,或者只提供易于检测的特殊形式的断言。
目前,还没有一个广泛使用的数据库系统支持在check
子句的谓词中使用子查询或create assertion
结构。
可以通过触发器来实现和断言等价的功能
然而,如果数据库系统支持触发器的话,可以通过使用触发器来实现等价的功能,
触发器将在5.3节介绍,5.3节还将介绍如何用触发器来实现time_slot_id
上的参照完整性约束。
MySQL
不支持断言create assertion
经过我的测试MySQL 8.0
好像不支持create assertion
断言。
原文链接: 4.4.7 复杂check条件与断言