第五章 数据库完整性
- 数据库的完整性指数据的真确性和相容性。
实体完整性
- 定义实体的完整性
- primary key
- 在列级定义主码
- 在表级定义主码
- primary key
- 实体完整性和违约处理
- 实体完整性检查
- 检查主码值是否唯一,如果不唯一则拒绝插入或修改。
- 检查主码的各个属性是否为空,只要有一个为空,则拒绝插入或修改。
- 检查主码唯一性的一个方法是进行全表扫描,关系数据库管理系统一般都在主码上建立一个索引,结构可以是B+树。
- 实体完整性检查
参照完整性
-
定义参照完整性
-
foreign key:定义表中的哪些列为外码。
-
reference :指明这些外码参照哪些表的主码。
create table sc( sno char(9) not null, cno char(4) not null, grade smallint, primary key(sno,cno), foreign key(sno) references student(sno), foreign key(cno) references course(cno) );
-
-
参照完整性检查和违约处理
-
一般地,当对参照表和被参照表的操作违反了参照完整性时,系统选用默认策略,即拒绝执行。
-
显式说明参照完整性的违约处理(多表关联,删除某一表时)
.... foreign key(sno) references student(sno) on delete cascade;#级联删除 .... foreign key(sno) references student(sno) on delete no action; #拒绝执行级联删除
-
用户定义的完整性
属性上的约束条件
- 约束条件的定义
- not null
- unique
- check(条件表达式)
- 属性上约束条件的检查和违约处理
- 当准备插入或修改数据时,如果属性不满足属性上的约束条件,则拒绝执行操作。
元组上的约束条件
-
定义
- 定义表时,在表的末尾天剑一个条件表达式
- check(Ssex=‘女’ or Sname not like ‘Ms.%’)
- 定义表时,在表的末尾天剑一个条件表达式
-
检查和违约处理
- 插入或修改数据时,不满足约束条件时,拒绝执行。
完整性约束命名子句
- 说明:对完整性条件约束 命名
-
完整性约束命名子句的使用
create table student( Sno number(6) constraint c1 check(Sno betweent 90000 and 99999), Sname char(20) constraint c2 not null, Sage number(3) constraint c3 check(Sage<30), Ssex number(1) constraint c4 check(Ssex in(0,1)), constraint c5 primary key(Sno) );
-
修改表中的完整性限制
-
先删除,再添加
alter table Studnet
drop constraint c1;
alter table Studnet
add constraint c1 check(sno beteween 900000 and 999999);
-
断言
- 特点:能够用来指定更有一般性的约束,可以涉及多个表或聚集操作的比较复杂的完整性约束。
- 断言创建以后,任何涉及对关系的操作都会,触发关系数据库管理系统对断言的检查,任何使断言不为真值的操作都会被拒绝执行。
- 如何断言很复杂,则系统在检测和维护断言的开销会较高,这是在使用断言时应该注意的。
-
断言的创建
create assertion <断言名><check 子句>
crete assertion asse_sc_db_num check (60>=( select count(*) form Course,SC where SC.cno=Course.cno and Course.Cname='数据库'));
- 当往SC表中插入一条元组时,asse_sc_db_num 就会被触发检查。当条件不满足时,操作就会被拒绝。
-
断言的删除
drop assertion<断言名>;
触发器
- 触发器又叫做 事件-条件-动作 规则。当特定的系统事件发生时,对规则的条件进行检查,如果条件成立则执行规则中的动作,否则不执行该动作。
-
定义触发器
create trigger <触发器名> {before | after} <触发事件> on <表名> #[触发的时机:操作前/后][insert/update..][table] referencing new | old row as <变量># for each{row | statement} # 行级/语句级 触发器 [when <触发条件>] <触发动作体>
-
例子:往教师表中插入、修改数据时,令教授工资>=4000
create tirgger Insert_or_update_Sal before insert or update on teacher referencing new row as newTuple #指出引用的变量;引用新插入元组时,元组的名字为newTuple for each row #行级触发器,每操作一个元组,执行一次该触发器 #when<触发条件> 满足条件时才触发 begin #触发动作体 if(newTuple.Job='教授') and (newTuple.Sal<4000) then newTuple.Sal=4000; end if; end
-
-
激活触发器
- 执行触发器指定的表的操作时,触发器自动执行
- 同一个表有多个触发器激活时顺序
- 执行该表上的before触发器
- 激活触发器的SQL语句
- 执行该表上的after触发器
注:对于同是before(after)的触发器,安装触发器创建的先后顺序执行
-
删除触发器
drop tirgger <触发器名> on <表名>;