4.4.5 参照完整性
参照完整性是什么
我们常常希望保证在一个关系中给定属性集上的取值也在另一关系的特定属性集的取值中出现。这种情况称为参照完整性(referential integrity
)。
正如我们此前在3.2.2
节所见,外码可以用作为SQL
中create table
语句一部分的foreign key
子句来声明。
我们用大学数据库SQL DLL
定义的一部分来说明外码声明:
1 | create table course( |
course
表的定义中有一个声明”foreign key(dept_name) references department
“。这个外码声明表示,在每个课程元组中指定的系名必须在department
关系中存在。没有这个约束,就可能会为一门课程指定一个不存在的系名。
什么是外码
更一般地,令关系r1
和r2
的属性集分别为R1
和R2
,主码分别为K1
和K2
。如果要求对r2
中任意元组t2
,均存在r1
中元组t1
使得t1.K1=t2.α
,我们称R2
的子集α
为参照关系r1
中K1
的外码(foreigkey
)。
参照完整性约束
这种要求称为参照完整性约束(referential-intergrity constraint)
或子集依赖( subset dependency
)。
子集依赖这种称法是由于上述参照完整性可以表示为这样一种要求:r2
中α
上的取值集合必须是r1
中K1
上的取值集合的子集
。
请注意,为使参照完整性约束有意义,α
和K1
必须是相容的属性集;也就是说,
要么α
等于K1
,
要么它们必须包含相同数目的属性,并且对应属性的类型必须相容(这里我们假设α
和K,
是有序的)。
参照完整性约束和外码约束的区别
- 默认情况下,
SQL
中外码参照的是
被参照表中的主码属性
。 - 不同于外码约束,参照完整性约束通常不要求
K1
是r1
的主码;其结果是,r1
中可能有不止个元组在属性K1
上取值相同。
个人总结
- 参照完整性约束要求有就行了,这可能会有重复.
- 外码约束不仅要有,还要唯一
references子句
SQL
还支持一个可以显式指定被参照关系的属性列表
的references
子句。
references子句指定的被参照关系的属性列表必须是候选码
然而,这个指定的属性列表必须声明为被参照关系的候选码,要么使用primary key
约束,要么使用unique
约束。
参照的属性不是候选码 的情况
在更为普遍的参照完整性约束形式中,被参照的属性不必是候选码,这样的形式还不能在SQL
中直接声明。SQL
标准提供了另外的结构用于实现这样的约束,4.4.7
节将描述这样的结构。
外码定义 示例
我们可以使用如下的简写形式作为属性定义的一部分,并声明该属性为外码:
1 | depr_name varchar(20) |
违反参照完整性约束时的做法
做法1 拒绝
当违反参照完整性约束时,通常的处理是拒绝执行导致完整性破坏的操作(即进行更新操作的事务被回滚)。
做法2 修改参照关系中的元组来恢复完整性
但是,在foreign key
子句中可以指明:如果被参照关系上的删除或更新动作违反了约束,那么系统必须采取一些步骤通过修改参照关系中的元组来恢复完整性约束,而不是拒绝这样的动作。考虑在关系course
上的如下完整性约束定义:
1 | create table course( |
级联删除
由于有了与外码声明相关联的on delete cascade
子句,
如果删除department
中的元组导致了此参照完整性约束被违反,则删除并不被系统拒绝,
而是对course
关系作”级联”删除,即删除course关系中参照被删除系名
的元组。
级联更新
类似地,如果更新被参照字段时违反了约束,则更新操作并不被系统拒绝,
而是将course
中参照的元组的dept_name
字段也改为新值。
设置为空或默认值
SQL
还允许foreign key
子句指明除cascade
以外的其他动作,例如:
- 用
set null
代替上面的cascade
,这样如果约束被违反:可将参照域(dept_name
)置为null
, - 用
set default
代替上面的cascade
,这样如果约束被违反:可将参照域(dept_name
)置为域的默认值。
级联更新或删除会传递
如果存在涉及多个关系的外码依赖链,则在链一端所做的删除或更新可能传至整个链。
级联更新或级联删除也无法解决 则撤销所有级联操作
如果个级联更新或删除导致的对约束的违反不能通过进一步的级联操作解决,则系统中止该事务。于是,该事务所做的所有改变及级联动作将被撤销。
外码可以为null
- 空值使得
SQL
中参照约束的语义复杂化了。外码中的属性允许为null,
只要它们没有被声明为not null
。 - 如果给定元组中
外码
的所有列上均取非空值
,则对该元组采用外码约束的通常定义。 - 如果某外码列为
null
,则该元组自动被认为满足约束 - 这样的规定有时不一定是正确的选择,因此
SQL
也提供一些结构使你可以改变对空值的处理,我们在此不讨论这样的结构。
原文链接: 4.4.5 参照完整性