约束:其可以对表中的数据做一些过滤,约束的主要功能是保证表中数据合法性,按照约束分类:共分5种约束:非空、唯一、主键、检查、主-外键约束。
1、非空约束(NK):当数据表中的某个字段上的内容不希望设置为null,则可以使用not null进行指定。
2、唯一约束(unique),UK:指每个列上的数据不允许重复。例如:email varchar(50) unique,此语句如果违反唯一约束条件,此时由系统默认分配一个违反约束代号,难以观察。但是也可以为唯一约束字段指定约束名称,其使用Constraint来定义,建议约束的名字格式“约束类型_字段”。
email varchar(50), constraint UK_email unique(email);
3、主键约束(primary key,PK):主键约束=非空+唯一约束,在之前设置唯一约束的时候发现可以设置为null,而如果使用了主键约束之后怎不能为空,并且主键一般作为数据的唯 一的一个标记出现。例如:ID number primary key;如果出现错误的数据则提示的信息和单一的非空、唯一约束提示的信息一样。所以这里也可以跟唯一约束一样,使用同样的命名方法,例如:constraint PK_ID primary key(ID);
(1)、在正常的开发角度而言,一张表一般只设置一个主键,但是从SQL语法的规定而言,一张表可以设置多个主键,这种做法称为复合主键。例如:
mid number, name vachar(50) not null,
constraint pk_mid_name primary key(mid, name);
在复合主键的使用中,只有两个字段的内容都一样的情况下,才被称为重复数据。
4、检查约束(Check,CK):指的是为表中的数据增加一些过滤条件。
create table member(
mid number, name varchar(50) not null
sex varchar(50) not null, age number(3),
constraint pk_mid primary key(mid),
constraint ck_sex check(sex in('男','女','中'),
constraint ck_age check(age between 1 to 250) );
5、主-外键约束:是建立在两张表中进行的,而且这两张表存在父子关系的,即:子表中某个字段的取值范围由父表所决定。
Drop table member purge;(删除不经过回收站)
Create table member( mid number,
name varchar(50) not null;
constraint pk_mid primary key(mid) );
create table book( bid number,
title varchar(50) not null, mid number,
constraint pk_bid primary key(bid),
constraint fk_mid foreign key(mid) references member(mid) );
此时,只是增加了一个约束,这样一来如果输入的数据有误,则会出现如下的提示:Scott.fk_mid未找到父项关键字。因为member.mid没有指定的数据,所以book.mid如果有数据错误,则无法执行更新操纵。不过,使用外键的最大好处是控制子表中某些数据的取值范围,但是在删除表的数据带来了不少的问题;
1、删除数据的时候,如果主表中的数据有对应的子表数据,则无法删除主表的对应数据;
例如:delete from member where mid=1;会提示违反约束,子表中有记录。此时,只能先删除子表记录,之后再删除父表记录。例如:Delete from book where mid=1;
delete from member where mid=1;
基于这种操作的不方便,可以通过建立外键约束的时候指定一个级联删除的功能,修改数据库创建脚本。
Drop table member purge;(删除不经过回收站)
Create table member( mid number,
name varchar(50) not null;
constraint pk_mid primary key(mid) );
create table book( bid number,
title varchar(50) not null, mid number,
constraint pk_bid primary key(bid),
constraint fk_mid foreign key(mid) references member(mid) [on delete cascade]|[on delete set null] );
此时由于存在级联删除的操作,所以主表中的数据删除之后,对应子表中的数据也都会被同时删除掉。
2、删除数据的时候,让子表中对应的数据设置为null,而不是删除,此时继续修改数据库创建脚本[on delete set null]。
3、删除父表之前首先删除对应的子表,否则无法删除。 例如:Drop table book purge;
drop table member purge;
但这样做比较麻烦,因为这样做必须知道表之间的父子关系。在Oralce之中专门提供了一个强制性删除表的操作,即:不再关心约束,在删除的时候写上一句“Cascade constraint”。
例如:Drop table member cascade constraint purge; 这样,不关心子表是否存在,直接强制性删除父表。不过,在以后进行数据表删除的时候,最好的惯用思想先删子表,后删父表。
6、修改约束 约束本身也属于数据库对吸纳,那么也肯定可以进行修改操作,而且只要修改都使用Alter指令,约束的修改主要指的是以下两种操作:
.为表增加约束:
Alter table 表名 ADD constraint 约束名 约束类型(字段);
.删除表中的约束:
Alter table 表名 drop constraint 约束名;
可以发现,如果要维护约束,肯定需要一个正确的名字才可以,可是在这五种约束之中,非空约束作为一个特殊的约束无法操作,例如:
drop table member cascade constraint purge;
create table member( mid number,
name varchar(50) not null, age number(3) );
范例:为表中增加主键约束
Alter table member Add constraint pk_mid primary key(mid);
alter table member add constraint ck_age check(age between 1 to 250);
范例:删除表主键约束
Alter table member drop constraint pk_mid;
7、查询约束
在oracle之中所有的对象都会在数据字典保存,而约束也是一样的,所以如果想要知道有哪些约束,可以直接查询“user_constraint”数据字典:select * from user_constraints;但是这个查询出来的约束只是列出名字,而并没有告诉在哪个字段上有此约束,所以此时可以查看另外一张数据字典表“user_cons_columns”;注另外种格式化:Col 字段名 for A列数;
col owner for A15;
col constraint_name for A15;
col table_name for A15;
col column_name for A15;
select owner,constraint_name,table_name,column_name from user_cons_columns;
---------------------------------------------------
数据库脚本:
1、建表:
DROP TABLE grade PURGE;
DROP TABLE sproter PURGE;
DROP TABLE item PURGE;
CREATE TABLE sporter(
sproterid number(4) primary key,
name varchar(20) not null,
sex varchar(10) check(sex in('男','女'),
department varchar(20) not null);
CREATE TABLE item(
itemid varchar(4) primary key,
itemName varchar(20) not null,
location varchar(20) not null);
CREATE TABLE grade(
sproterid number(4) references sporter(sporterid) on delete cascade,
itemid varchar(4) references item(itemid) on delete cascade,
mark number(1) check(mark in(0,2,4,6));
2、增加数据
运动员(1001,李明,男,计算机系
1002,张三,男,数学系
1003,李四,男,计算机系
1004,王二,男,物理系
1005,李娜,女,心理系
1006,孙俪,女,数学系)
insert into sporter(sproterid, name,sex,department) values(1001,'李明','男','计算机系');
... ...
项目(x001,男子五千米,一操场
... ...)
insert into item(itemid, itemName, location) values('x001','男子五千米','一操场');
... ...
积分(1001,x001, 6
... ...)
insert into grade(sporterid, itemid, mark) values(1001,'x001', 6);
... ...
3、数据操作
。求出目前积分最高的系名,及其积分
.确定所需的数据表:
|-sporter表;
|-grade表;
.确定已知关联字段:
sproter.sproterid=grade.sporterid
执行:select s.department, sum(g.mark)
from sporter s, grader g
where s.sporterid=g.sporterid
【得到系和积分。】
group by s.department
【得到系和总积分】
做法一:不考虑相同积分的问题,所有数据由高->低,取第一个数据;
select * from( select s.department,sum(g.mark)
from sporter s, grader g
where s.sporterid=g.sporterid
group by s.department, sum desc) where rownum=1;
做法二:考虑相同积分的问题,则必须首先进行分组函数的嵌套,求出最高积分是多少,而后再用此内容与之前的分组进行过滤。
select s.department, sum(g.mark) sum from sproter s, grade g where s.sporterid=g.sporterid group by s.department having sum(g.mark)=(select Max(sum(g.mark)) sum from sporter s, grade g where s.sporterid=g.spoeterid
group by s.department);
--------------------------------------------------