关于oracle的学习记录:
四十、约束的创建与管理(外键约束)难点
单纯的解释外键并不好解释,下面通过一个数据表的操作来观察一下为什么需要外键,外键与其他约束不同,它是作用在两张数据表上的约束
范例:问题分析
在之前使用的是dept-emp表,这个表的基本关系是每一个部门可以包含有多个雇员信息,属于一对多关系,dept是一个父表,emp是一个子表,所以在emp子表里面设置有一个deptno的字段
模拟以上的功能实现一个人有多本书的操作,很明显,需要定义两张表:
drop table member purge;
drop table book purge;
create table member(
mid number,
name varchar2(20) not null,
constraint pk_mid primary key(mid)
);
create table book(
bid number,
title varchar2(20),
mid number,
constraint pk_bid primary key(bid)
);
下面开始增加数据
范例:增加有意义的数据
insert into member(mid,name) values(10,’张三’);
insert into member(mid,name) values(20,’李四’);
insert into member(mid,name) values(30,’王五’);
insert into book(bid,title,mid) values(10001,’java’,10);
insert into book(bid,title,mid) values(10002,’jsp’,10);
insert into book(bid,title,mid) values(10003,’mvc’,10);
insert into book(bid,title,mid) values(20001,’oracle’,20);
insert into book(bid,title,mid) values(20002,’db2′,20);
insert into book(bid,title,mid) values(20003,’mongo’,20);
insert into book(bid,title,mid) values(30001,’jquery’,30);
insert into book(bid,title,mid) values(30002,’angularjs’,30);
所有增加的信息中的人员编号在member里面都存在
范例:增加错误信息
insert into book(bid,title,mid) values(88888,’心灵之船’,90);
明明在member里面没有”mid=90″的人员信息,但是在book表里面这样的信息却可以保存,以上代码的问题出现在:子表中的数据与父表中的数据不一致(book子表中的mid的取值范围应该由父表member中的mid来决定)
所以所谓的外键关联指的就是控制子表中某一列的内容与父表中的数据范围相匹配,使用foreign key(fk)来表示
范例:增加外键
drop table member purge;
drop table book purge;
create table member(
mid number,
name varchar2(20) not null,
constraint pk_mid primary key(mid)
);
create table book(
bid number,
title varchar2(20),
mid number,
constraint pk_bid primary key(bid),
constraint fk_mid foreign key(mid) references member(mid)
);
范例:增加正确信息
insert into member(mid,name) values(10,’张三’);
insert into member(mid,name) values(20,’李四’);
insert into member(mid,name) values(30,’王五’);
insert into book(bid,title,mid) values(10001,’java’,10);
insert into book(bid,title,mid) values(10002,’jsp’,10);
insert into book(bid,title,mid) values(10003,’mvc’,10);
insert into book(bid,title,mid) values(20001,’oracle’,20);
insert into book(bid,title,mid) values(20002,’db2′,20);
insert into book(bid,title,mid) values(20003,’mongo’,20);
insert into book(bid,title,mid) values(30001,’jquery’,30);
insert into book(bid,title,mid) values(30002,’angularjs’,30);
如果此时关联的数据正确,那么可以正常的保存,如果此时book表中要增加的数据关联有问题(父表不存在此内容),就会出现以下提示:
insert into book(bid,title,mid) values(88888,’心灵之船’,90);
ora-02291:违反完整约束条件(scott.fk_mid)-未找到父项关键字
因为在member表的mid列上没有内容为90的数据,所以以上的错误数据无法保存
虽然清楚了外键的作用,但是一旦使用到了外键那么就比较麻烦了,因为所有的约束中,外键是针对于两张表的约束,所以在表对象与表数据的操作上就会存在限制:
|–限制1:如果表中存在有外键关系,在删除父表前一定要先删除子表
drop table book purge;
drop table member purge;
以上是编写代码的正常逻辑,如果假设现在有两张表a和b,a表有b表的外键,b表有a表的外键,这个就没法区分了,所以提供有一种强制删除
范例:强制删除
drop tabel member cascade constraint;
此时,不再灌注子表是否存在,父表直接删除,不到万不得已不要使用
|–限制2:父表中作为子表关联的外键字段,必须设置为主键约束或唯一约束
|–限制3:默认情况下,如果父表记录中有对应的子表记录,那么父表记录无法被删除
delete from member where mid=10;
ora-02292:违反完整约束条件(scott.fk_mid)-已找到子记录
因为在book表中存在有member表对应记录的子内容,如果要想删除则应该先删除子表数据后再删除父表记录
delete from book where mid=10;
delete from member where mid=10;
如果说此时member表与10张表都存在有外键关系,这样先删除子表再删除父表的过程就不方便了,有些时候,希望一删除父表数据,对应子表数据都自动删除完了,那么这就需要配置数据的级联操作。
**数据的级联删除:on delete cascade
如:
drop table member purge;
drop table book purge;
create table member(
mid number,
name varchar2(20) not null,
constraint pk_mid primary key(mid)
);
create table book(
bid number,
title varchar2(20),
mid number,
constraint pk_bid primary key(bid),
constraint fk_mid foreign key(mid) references member(mid) on delete cascade
);
**级联更新:当父表数据被删除后,子表对应的内容设置为null,使用:on delete set null
如:
drop table member purge;
drop table book purge;
create table member(
mid number,
name varchar2(20) not null,
constraint pk_mid primary key(mid)
);
create table book(
bid number,
title varchar2(20),
mid number,
constraint pk_bid primary key(bid),
constraint fk_mid foreign key(mid) references member(mid) on delete set null
);
是否选择数据的级联操作,或者选择哪种级联是根据开发要求来决定的