d,name,sex,age) VALUES(1,'张三','男','26'); 范例:增加错误的性别 ―― ORA-02290: 违反检查约束条件 (SCOTT.CK_SEX)
INSERT INTO member(mid,name,sex,age) VALUES(2,'李四','非','26');
范例:增加错误的年龄 ―― ORA-02290: 违反检查约束条件 (SCOTT.CK_AGE)
INSERT INTO member(mid,name,sex,age) VALUES(2,'李四','女','260');
检查的操作就是对输入的数据进行一个过滤。
五、主-外键约束
之前的四种约束都是在单张表中进行的,而主-外键约束是在两张表中进行的,这两张表是存在父子关系的,即:子表中某个字段的取值范围由父表所决定。
例如,现在要求表示出一种关系,每一个人有多本书,应该定义两张数据表:member(主)、book(子);
DROP TABLE member PURGE;
DROP TABLE book PURGE;
CREATE TABLE member(
mid NUMBER,
name VARCHAR2(50) NOT NULL,
CONSTRAINT pk_mid PRIMARY KEY(mid)
);
CREATE TABLE book(
bid NUMBER,
title VARCHAR2(50) NOT NULL,
mid NUMBER,
CONSTRAINT pk_bid PRIMARY KEY(bid)
);
此时只是根据要求建立了两张独立的数据表,那么下面插入几条数据:
INSERT INTO member(mid,name) VALUES(1,'张三');
INSERT INTO member(mid,name) VALUES(2,'李四');
INSERT INTO book(bid,title,mid) VALUES(101,'Java开发',1);
INSERT INTO book(bid,title,mid) VALUES(102,'Java Web开发',2);
INSERT INTO book(bid,title,mid) VALUES(103,'EJB开发',2);
INSERT INTO book(bid,title,mid) VALUES(105,'Android开发',1);
INSERT INTO book(bid,title,mid) VALUES(107,'AJAX开发',1);
要想验证这个数据是否有意义,最简单的做法,就是写两个查询。
范例:统计每个人员拥有书的数量
SELECT m.mid,m.name,COUNT(b.bid)
FROM member m,book b
WHERE m.mid=b.mid
GROUP BY m.mid,m.name;
范例:查询出每个人员的编号,姓名,拥有书的名称
SELECT m.mid,m.name,b.title
FROM member m,book b
WHERE m.mid=b.mid;
即,现在的book.mid字段应该是与member.mid字段相关联的,但是由于本程序没有设置约束,所以,现在以下的数据也是可以增加的:
INSERT INTO book(bid,title,mid) VALUES(108,'PhotoShop使用手册',3);
INSERT INTO book(bid,title,mid) VALUES(109,'FLEX开发手册',8);
现在增加了两条新的记录,而且记录可以保存在数据表之中,但是这两条记录没有意义,因为member.mid字段的内容没有3和8,而要想解决这个问题就必须依靠外键约束来解决。
让book.mid的字段的取值由member.mid所决定,如果member.mid的数据真实存在,则表示可以更新。
DROP TABLE member PURGE;
DROP TABLE book PURGE;
CREATE TABLE member(
mid NUMBER,
name VARCHAR2(50) NOT NULL,
CONSTRAINT pk_mid PRIMARY KEY(mid)
);
CREATE TABLE book(
bid NUMBER,
title VARCHAR2(50) NOT NULL,
mid NUMBER,
CONSTRAINT pk_bid PRIMARY KEY(bid),
CONSTRAINT fk_mid FOREIGN KEY(mid) REFERENCES member(mid)
);
此时,只是增加了一个约束,这样一来如果输入的数据有错误,则会出现如下的提示:
ORA-02291: 违反完整约束条件 (SCOTT.FK_MID) - 未找到父项关键字
因为member.mid没有指定的数据,所以book.mid如果数据有错误,则无法执行更新操作。
使用外键的最大好处是控制了子表中某些数据的取值范围,但是同样带来了不少的问题;
1、 删除数据的时候,如果主表中的数据有对应的子表数据,则无法删除;
范例:删除member表中mid为1的数据
DELETE FROM member WHERE mid=1;
错误提示信息:“ORA-02292: 违反完整约束条件 (SCOTT.FK_MID) - 已找到子记录”。
此时,只能先删除子表记录,之后再删除父表记录:
DELETE FROM book WHERE mid=1;
DELETE FROM member WHERE mid=1;
但是这种操作明显不方便,如果说现在希望主表数据删除之后,子表中对应的数据也可以删除的话,则可以在建立外键约束的时候指定一个级联删除的功能,修改数据库创建脚本:
DROP TABLE member PURGE;
DROP TABLE book PURGE;
CREATE TABLE member(
mid NUMBER,
name VARCHAR2(50) NOT NULL,
CONSTRAINT pk_mid PRIMARY KEY(mid)
);
CREATE TABLE book(
bid NUMBER,
title VARCHAR2(50) NOT NULL,
mid NUMBER,
CONSTRAINT pk_bid PRIMARY KEY(bid),
CONSTRAINT fk_mid FOREIGN KEY(mid) REFERENCES member(mid) ON DELETE CASCADE
);
此时由于存在级联删除的操作,所以主表中的数据删除之后,对应的子表中的数据也都会被同时删除。
2、 删除数据的时候,让子表中对应的数据设置为null
当主表中的数据删除之后,对应的子表中的数据相关项也希望将其设置为null,而不是删除,此时,可以继续修改数据表的创建脚本:
DROP TABLE member PURGE;
DROP TABLE book PURGE;
CREATE TABLE member(
mid NUMBER,
name VARCHAR2(50) NOT NULL,
CONSTRAINT pk_mid PRIMARY KEY(mid)
);
CREATE TABLE book(
bid NUMBER,
title VARCHAR2(50) NOT NULL,
mid NUMBER,
CONSTRAINT pk_bid PRIMARY KEY(bid),
CONSTRAINT fk_mid FOREIGN KEY(mid) REFERENCES member(mid) ON