之前在项目中遇到了这样一个问题,我举得简单的例子来说明,
比如我们有两个表,一个表(department)存放的是部门的信息,例如部门id,部门名称等;另一个表是员工表(staff),员工表里面肯定要存放每个员工所在的部门。那问题来了,如果我们这个时候删除了部门表中的某条记录,在staff表中会发生什么?
为了解答上面的问题,让我们先来回顾一下什么是参照完整性。
我们常常希望保证在一个关系中给定属性集上的取值也在另一个关系的特定属性集的取值中出现。这种情况称为参照完整性(referential integrity)
正如我们可以用外码在SQL中的create table语句一部分的foreign key子句来声名。
例如staff表中的我们可以用 foreign key(dep_name) references department 来表明在每个员工组中指定的部门名称dep_name必须在department关系中存在。
更一般地,令关系r1和r2的属性集分别为R1和R2,主码分别为K1和K2。如果要求对r2中任意元祖t2,均存在r1中元祖t1使得t1.K1 = t2.α,我们称R2的子集α为参照关系r1中K1的外码(foreign key)
当我们违反了参照完整性约束时,通常的处理是拒绝执行导致完整性破坏的操作(即进行更新操作的事务被回滚)。但是,在foreign key子句中可以指明:如果被参照关系上的删除或更新动作违反了约束,那么系统必须采取一些步骤通过修改参照关系中的元祖来恢复完整性约束,而不是拒绝这样的操作。
来看下面的例子:
这是我们的department关系
create table department ( dept_name varchar(20), building varchar(15), primary key(department) )
下面一般情况下我们的staff关系
<pre name="code" class="sql">create table staff ( ID varchar(15), name varchar(20), not null dept_name varchar(20), primary key (ID), foreign key(dept_name) reference department )
create table staff ( ID varchar(15), name varchar(20), not null dept_name varchar(20), primary key (ID), foreign key(dept_name) reference department on delete cascade on update cascade )
但是,一般来说,我们习惯的用法是,不允许删除。如果实在要删除,可以在被参照关系中加一个字段,来表明当前的记录被删除了,这样也方便日后查询等相关操作。