之前所讲解的全部约束都是针对于一张表的约束,那么主-外键约束是针对于两张表的约束。
为什么需要主-外键约束?
范例:要求完成一个程序,一本书要属于一个人
·书本身应该是一张表,一个书中必然有一个字段表示属于哪个人的
DROP TABLE person; DROP TABLE book; CREATE TABLE person( pid VARCHAR2(18), name VARCHAR2(200) NOT NULL, age NUMBER(3) NOT NULL, birthday DATE, sex VARCHAR2(2) DEFAULT '男', CONSTRAINT person_pid_pk PRIMARY KEY(pid), CONSTRAINT person_name_uk UNIQUE(name) , CONSTRAINT person_age_ck CHECK(age BETWEEN 0 AND 150), CONSTRAINT person_sex_ck CHECK(sex IN ('男','女','中')) ); CREATE TABLE book( bid NUMBER PRIMARY KEY NOT NULL, bname VARCHAR2(30), bprice NUMBER(5,2), pid VARCHAR(18) ); |
创建完两张表之后,下一步插入一些测试数据:
INSERT INTO person(pid,name,age,birthday,sex) VALUES ('111111111111111111','张三',33,TO_DATE('1976-02-13','yyyy-mm-dd'),'女'); INSERT INTO book(bid,bname,bprice,pid) VALUES (1,'JAVA SE',89.9,'111111111111111111'); |
确实可以符合要求,但是如果现在插入了以下数据:
INSERT INTO book(bid,bname,bprice,pid) VALUES (2,'JAVA SE',89.9,'000000000000000000'); |
此编号的人员并不存在,如果不存在,则此数据肯定不应该插入。此时,如果要想解决这样的问题,则肯定要使用主-外键关联,关联之后子表的数据要跟随父表的数据内容。
父表:person 子表:book DROP TABLE person; DROP TABLE book; CREATE TABLE person( pid VARCHAR2(18), name VARCHAR2(200) NOT NULL, age NUMBER(3) NOT NULL, birthday DATE, sex VARCHAR2(2) DEFAULT '男', CONSTRAINT person_pid_pk PRIMARY KEY(pid), CONSTRAINT person_name_uk UNIQUE(name) , CONSTRAINT person_age_ck CHECK(age BETWEEN 0 AND 150), CONSTRAINT person_sex_ck CHECK(sex IN ('男','女','中')) ); CREATE TABLE book( bid NUMBER PRIMARY KEY NOT NULL, bname VARCHAR2(30), bprice NUMBER(5,2), pid VARCHAR(18), CONSTRAINT person_book_pid_fk FOREIGN KEY(pid) REFERENCES person(pid) ); |
此时,再次执行数据的插入操作
此时,可以保证两张表的数据完整性,不会出现找不到对应数据的情况。
在使用主-外键关联的时候也要有以下的注意点:
·在子表中设置的外键在父表中必须是主键
·删除时应该先删除子表,再删除父表
DROP TABLE person; DROP TABLE book; |
说明现在根本无法删除子表,因为存在这样的关联关系
DROP TABLE book; DROP TABLE person; |
可以使用强制性的删除手段:
DROP TABLE person CASCADE CONSTRAINT; |
不管约束,而直接删除,但是这种做法一般不使用。
回顾:
咱们之前学习的emp和dept表,实际上这两张表也是有主-外键关联的。
范例:现在向emp表中增加一个50部门的员工
·在dept表中本身并不存在50部门的部门编号
INSERT INTO emp(empno,ename,job,sal,mgr,hiredate,comm,deptno) VALUES(8888,'张三','经理',90000,null,sysdate,null,50); |
此时,提示没有找到父项的关键字,所以无法插入成功。
在主-外键关联中也可以使用级联删除的情况。
·以现在数据库中的数据为例。
DELETE FROM person WHERE pid='111111111111111111'; |
要删除person表中编号为“”的人员,但是此人员现在在book表中存在一本书。
因为在子表中存在此项的关联,所以无法删除,那么,此时如果要想完成删除操作的话,则必须先将book表中对应的数据删除掉。
如果,希望一个表中的数据在删除时,可以自动删除掉其对应的子表记录,则就可以使用级联删除的操作。
DROP TABLE book; DROP TABLE person; CREATE TABLE person( pid VARCHAR2(18), name VARCHAR2(200) NOT NULL, age NUMBER(3) NOT NULL, birthday DATE, sex VARCHAR2(2) DEFAULT '男', CONSTRAINT person_pid_pk PRIMARY KEY(pid), CONSTRAINT person_name_uk UNIQUE(name) , CONSTRAINT person_age_ck CHECK(age BETWEEN 0 AND 150), CONSTRAINT person_sex_ck CHECK(sex IN ('男','女','中')) ); CREATE TABLE book( bid NUMBER PRIMARY KEY NOT NULL, bname VARCHAR2(30), bprice NUMBER(5,2), pid VARCHAR(18), CONSTRAINT person_book_pid_fk FOREIGN KEY(pid) REFERENCES person(pid) ON DELETE CASCADE ); INSERT INTO person(pid,name,age,birthday,sex) VALUES ('111111111111111111','张三',33,TO_DATE('1976-02-13','yyyy-mm-dd'),'女'); INSERT INTO book(bid,bname,bprice,pid) VALUES (1,'JAVA SE',89.9,'111111111111111111'); |
更改表结构,之后再次执行删除操作
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/21817401/viewspace-620326/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/21817401/viewspace-620326/