Chinaunix首页 | 论坛 | 博客
  • 博客访问: 101577
  • 博文数量: 35
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 302
  • 用 户 组: 普通用户
  • 注册时间: 2017-02-07 17:04
个人简介

不积跬步无以至千里,每天进步一点点~

文章分类

全部博文(35)

文章存档

2018年(3)

2017年(32)

我的朋友

分类: Oracle

2017-11-30 10:25:00

完整性约束:
完整性约束是保证用户对数据库所做的修改不会破坏数据的一致性,是保护数据正确性和相容性的一种手段。
维护完整性:在一个DBMS之中,为了能够维护数据库的完整性,必须能够提供以下的几种支持:
  提供定义完整性约束条件机制:在数据表上定义规则,这些规则是数据库中的数据
  必须满足的语义约束条件;
  提供完整性检查的方法:在更新数据库是检查更新数据是否满足完整性约束条件。
  违约处理:DBMS发现数据违反了完整性约束后要求采取的违约处理行为,如拒绝
  (no action)执行该操作,或者级联(cascade)执行其他操作。
在开发之中可以使用以下五种约束进行定义:
非空约束:如果使用了非空约束的话,则以后此字段的内容不允许设置成null;
唯一约束:即:此列的内容不允许出现重复。
主键约束:表示一个唯一的标识,例如:人员ID不能重复,且不能为空;
检查约束:用户自行编写设置内容的检查条件;
主-外键约束(参照完整性约束):是在两张表上进行的关联约束,加入关联约束之后就
产生父子的关系。
1.非空约束:NK
在正常情况下,null是每个属性的合法数据值。如果说现在某个字段不能为null,
且必须存在数据,那么就可以依靠非空约束来进行控制,这样在数据更新时,此字段
的内容出现null时就会产生错误。
范例:定义member表,其中姓名不允许为空
drop table member purge;
create table member(
mid number,
name varchar2(200) not null
);
insert into member (mid,name)values(1,'Wings' );
insert into member (mid,name)values(2,'King' );
desc member;
select *from member;
非空约束不允许字段为null,非空约束出现错误时会提示完整的错误位置。

2.主键约束:PK
如果一个字段即要求唯一,又不能设置为null,则可以使用主键约束(主键约束=非空约束+唯一约束),
主键约束使用primary key进行指定,例如:在member表中的mid字段应该表示一个成员的唯一编号,
而这个编号即不能为空,也不能重复。

范例:
drop table member purge;
create table member(
  mid number primary key,
  name varchar2(50),
  email varchar2(50),
  constraint UK_email unique(email)
)
insert into member (mid,name,email) values(null,'King','king@qq.com');
insert into member (mid,name,email) values(1,'King','king@qq.com');

insert into member (mid,name,email) values(1,'King','king@qq.com');
SQL 错误: ORA-00001: 违反唯一约束条件 (C##SCOTT.SYS_C0011994)
00001. 00000 -  "unique constraint (%s.%s) violated"
指定主键约束的名称
drop table member purge;
create table member(
mid number,
name varchar2(50),
email varchar2(50),
constraint PK_mid primary key (mid),
constraint UK_email unique (email)
)
insert into member (mid,name,email) values(1,'King','king@qq.com');
insert into member (mid,name,email) values(1,'King','king@qq.com');
SQL 错误: ORA-00001: 违反唯一约束条件 (C##SCOTT.PK_MID)
在以后的开发过程中,只要是实体表数据。都需要一个主键,而一些关系表有可能没有主键。

复合主键
在实际的开发中,一般一张表中只会设置一个主键,但是也允许为一张表设置多个主键,这个
时候将其称为复合主键。在复合主键中,只有两个主键字段内容完全一样,才会发生违反约束
的错误。注意:复合主键尽量不要用。
范例:
drop table member purge;
create table member(
 mid number,
 name varchar2(50),
 email varchar2(50),
 constraint pk_mid_name primary key (mid,name),
 constraint uk_email unique (email)
)

3.检查约束:CK
范例:
drop table member purge;
create table member(
mid number,
name varchar2(50),
email varchar2(50),
age  number,
sex varchar2(5),
constraint pk_mid_name primary key (mid,name),
constraint uk_email unique (email),
constraint ck_age check(age between 0 and 200),
constraint ck_sex check(sex in('男','女'))
);
插入错误数据:
insert into member(mid,name,email,age,sex)values(2,'King','King@163.com',1000,'男');
select * from member;
注意:关于性能问题
对于任何一种操作,如果增加的检查约束越多,那么实际上一定会影响更新的性能,
所以一张数据表如果被频繁修改的话,不建议使用检查约束。所以这样的验证操作,
一般都由程序完成,例如:struts中的各种验证。
4.外键约束:FK
drop table member purge;
drop table advice purge;
create table member(
mid number,
name varchar2(50) not null,
constraint pk_mid primary key (mid)
);
create table advice(
adid number,
content clob not null,
mid number,
constraint pk_adid primary key (adid)
);
insert into member (mid,name) values (1,'KIng');
insert into member (mid,name) values (2,'WIng');
insert into advice (adid,content,mid)values(1,'建议给我涨工资',1);
insert into advice (adid,content,mid)values(2,'建议给我涨工资',2);
insert into advice (adid,content,mid)values(3,'建议加强员工关怀',1);
insert into advice (adid,content,mid)values(4,'建议加强体育锻炼',2);
insert into advice (adid,content,mid)values(5,'建议多多交流',2);
select * from advice;
范例:查出每位成员的完整信息以及所提出的意见数量。
select m.mid , m.name,count(a.mid) 
from member m,advice a
where m.mid=a.mid
group by m.mid,m.name
插入一条错误数据:
insert into advice (adid,content,mid)values(6,'建议给我升官',55);
插入成功,但是member表里面没有55号员工。可以发现如果按照之前所学的技术来讲,
这种错误的数据无法回避,那么现在实际上就来分析一下,关于数据的参考方式。
现在对于表可以分为父表(member)子表(advice),因为子表之中的数据必须参考
member表中的数据。建议提出这的成员编号应该是在member表中mid列上所存在的数据。
所以在这样的情况下,为了保证表中的数据有效性,就只能够利用外键约束来完成。
外键使用foreign key来进行设置。
范例:增加外键的配置。
drop table member purge;
drop table advice purge;
create table member(
mid number,
name varchar2(50) not null,
constraint pk_mid primary key (mid)
);
create table advice(
adid number,
content clob not null,
mid number,
constraint pk_adid primary key (adid),
constraint fk_mid foreign key(mid) references member(mid)
);
insert into member (mid,name) values (1,'KIng');
insert into member (mid,name) values (2,'WIng');
insert into advice (adid,content,mid)values(1,'建议给我涨工资',1);
insert into advice (adid,content,mid)values(2,'建议给我涨工资',2);
insert into advice (adid,content,mid)values(3,'建议加强员工关怀',1);
insert into advice (adid,content,mid)values(4,'建议加强体育锻炼',2);
insert into advice (adid,content,mid)values(5,'建议多多交流',2);
插入错误数据:
insert into advice (adid,content,mid)values(6,'建议给我升官',55);
SQL 错误: ORA-02291: 违反完整约束条件 (C##SCOTT.FK_MID) - 未找到父项关键字

可是一旦为表中增加了外键,就会有新的问题出现。
问题一:如果要删除父表数据,那么首先必须要先删除对应的所有子表数据。
范例:删除主表中的数据。
delete from member where mid=1
SQL 错误: ORA-02292: 违反完整约束条件 (C##SCOTT.FK_MID) - 已找到子记录
如果现在非要删除,就需要先删除子表中的数据。
delete from advice where mid=1;
delete from member where mid=1;
但是这样的做法也不合适。主表的记录被控制的太过了。为了解决外键中的数据的操作问题,
就提出了数据的级联操作。
1).级联操作一:级联删除on delete cascade,当主表数据被删除之后,对应的子表数据
也应该同事被清理。
范例:配置级联删除。
drop table advice purge;
drop table member purge;
create table member(
mid number,
name varchar2(50) not null,
constraint pk_mid primary key (mid)
);
create table advice(
adid number,
content clob not null,
mid number,
constraint pk_adid primary key (adid),
constraint fk_mid foreign key(mid) references member(mid) on delete cascade
);
insert into member (mid,name) values (1,'King');
insert into member (mid,name) values (2,'Wing');
insert into advice (adid,content,mid)values(1,'建议给我涨工资',1);
insert into advice (adid,content,mid)values(2,'建议给我涨工资',2);
insert into advice (adid,content,mid)values(3,'建议加强员工关怀',1);
insert into advice (adid,content,mid)values(4,'建议加强体育锻炼',2);
insert into advice (adid,content,mid)values(5,'建议多多交流',2);
这个时候只删除父表中的记录,而所有对应的子表记录同事也被删除。
delete from member where mid=1;
select * from advice;
2).级联操作二:级联更新。on delete set null
当主表数据被删除之后,对应的子表数据的相应字段内容会设置成null。
drop table advice purge;
drop table member purge;
create table member(
mid number,
name varchar2(50) not null,
constraint pk_mid primary key (mid)
);
create table advice(
adid number,
content clob not null,
mid number,
constraint pk_adid primary key (adid),
constraint fk_mid foreign key(mid) references member(mid) on delete set null
);
insert into member (mid,name) values (1,'King');
insert into member (mid,name) values (2,'Wing');
insert into advice (adid,content,mid)values(1,'建议给我涨工资',1);
insert into advice (adid,content,mid)values(2,'建议给我涨工资',2);
insert into advice (adid,content,mid)values(3,'建议加强员工关怀',1);
insert into advice (adid,content,mid)values(4,'建议加强体育锻炼',2);
insert into advice (adid,content,mid)values(5,'建议多多交流',2);
delete from member where mid=1;
select * from advice;
以上的级联操作选择还是看需求。
问题二:删除父表的时候需要先删除子表
而且在此处还有一点小的说明,在进行外键设置的时候,对应字段,在父表中
必须是主键或者是唯一约束。
但是有的时候,非常规的情况:将A表作为B表的父表,而又通过修改,将B表作为了
A表的父表,等于这两张表互为外键。这种混乱的情况可以选择强制性删除。
drop table member cascade constraint;
注意:而这种强制删除虽然干净快捷,但是不建议使用。主要是因为在编写数据库创建脚本的时候
一定要考虑好这先后的关系。
5.查看约束:
约束是由数据自己创建的对象,所有对象都会在数据字典之中进行保存。
可以利用user_constraints数据字典或者是user_cons_columns数据
字典查看。
drop table advice purge;
drop table member purge;
purge recyclebin;
select * from tab;
create table member(
mid number primary key,
name varchar2(50) not null
)
desc member;
insert into member (mid,name)values(1,'张三');
insert into member (mid,name)values(2,'李四');
insert into member (mid,name)values(1,'王五');
SQL 错误: ORA-00001: 违反唯一约束条件 (C##SCOTT.SYS_C0012116)
select * from user_constraints;
select * from user_cons_columns;
查询结果:C##SCOTT SYS_C0012116 MEMBER MID 1
可以看出,错误编号跟mid字段对应。
但是一般而言,如果按照标准的开发模式,按照“约束简写_字段”实际上就够解决
这些约束简称的问题了。从开发角度讲约束的名称一定有。

6.修改约束:
不建议修改,只做语法了解。
1)增加约束
如果一张表创建的时候没有创建任何约束,就可以通过指定的语法
实现约束的增加。
范例:定义一张没有约束的表


drop table member purge;
create table member(
mid number,
name varchar2(50),
age number
);
select * from user_constraints where table_name='MEMBER';--查看约束为空
为表中增加约束:
语法:alter table 表名称 add constraint 约束名称 约束类型(约束字段);
范例:为member表的mid字段增加主键约束
alter table member add constraint pk_mid primary key (mid);
范例:为member表的age字段增加检查约束
alter table member add constraint ck_age check(age between 0 and 200);
desc member;
但是有一点需要说明的是,在进行约束后期添加的时候,非空约束不能够用此类语法。
非空约束只能通过修改表结构的方式。
alter table member add constraint nk_name not null;--失败
alter table member modify(name varchar2(50) not null);
而且后期的约束添加,必须有一个条件,表中存放的数据本身是不存在违反约束条件的。
2)启用/禁用约束
打部分情况下一张表一定会定义多种约束,但是约束过多一定会影响到性能,所以当需要
大批量数据更新的时候,就希望约束暂时停一下。
禁用约束:
alter table 表名称 disable constraint 约束名称[cascade];
范例:禁用adive 表中的adid 主键约束'pk_adid'
  alter table advice disable constraint pk_adid;
范例:禁用member表中的‘PK_mid’约束,此字段在advice表中是外键
  alter table member disable constraint pk_mid;--因为外键问题,禁用失败
   alter table member disable constraint pk_mid cascade;--正确

启用约束:
alter table 表名称 enable constraint 约束名称;
如果要保证主键约束启动成功,必须先解决表中数据重复问题。
删除约束:
约束属于数据库对象,所以对象也可以删除。
alter table 表名称 drop constraint 约束名称[cascade]
范例:删除advice表中的pk_adid约束--无外键关联
alter table advice drop constraint pk_adid;
范例:删除member表中的pk_mid约束--有外键关联
alter table advice drop constraint pk_mid cascade;
注意:约束一定要和表一起建立,最低的限度也应该在数据库正式使用之前建立好
完善的约束,不要想着后期进行约束的弥补。





阅读(1464) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~