概念:指数据的正确性和相容性
完整性:指数据符合现实世界的语义(比如学号必须唯一)
相容性:指数据库中同一对象在不同关系表中是符合逻辑的(学生选的课必须存在与选课表中)
5.1到5.3在之前的第三章都基本学过。
5.1 实体完整性
5.1.1 定义
关系模式的实体完整性:设置主码 primary key
单属性:可以在列级和表级进行定义:例:
sno char(10)primary key or primary key(sno)
多属性:只能在表级 例:
primary key(sno,cno)
5.1.2 实体性完整性检查和违约处理
完整性检查:每当主码列进行更新后,
检查主码值是否唯一,如果不唯一则拒绝修改
检查各个属性是否为空,只要有一个为空就拒绝修改
检查主码方式:全盘扫描,全盘扫描是十分耗时的,关系数据库管理系统一般都会采取B+数索引(详情请转数据结构)
5.2 参照完整性
5.2.1定义
定义:设置外码 例:
foreign key(xxx) reference 表名(xxx)
表级foreign:外国的,涉外的
reference:参考
5.2.2 参照性完整性检查和违约处理
参照性完整性将两个表中的相应元组联系起来了
违约处理规则:
拒绝:一般为默认策略
级联:当删除或者修改被参照表中的一个元组时,使得与参照表不一样的时候,则将参照表中对应的元素也修改了 通俗点:你参照人家的,人家改了,你这也得改
设置为空值:当删除或者修改被参照表中的一个元组时,使得与参照表不一样的时候,则将参照表中对应的属性设置为空值。人家改了或者删了,我也有不参考他的权力,那我也就置为空了
SQL中使用级联、拒绝、设为空
foreign key(sno) reference student(sno)//sno是sc表中参照与student表的元素
on delete cascade //当删除student中的元组时,删除sc表中对应的元组
on update cascade//当更新student表中的sno时,更新sc表中的元素
foreign key(cno) reference course(cno)
on delete no action//当删除course表中的元组造成与sc表中不一致时,拒绝删除
5.3 用户定义的完整性
5.3.1属性上的约束条件
非空 not null
列值唯一 unique
检查列值 check短语
如果不满足直接拒绝执行
5.3.2 元组上的约束条件
上边上的check是对每一列
当然也可以在整个元组进行检查
写在最后而不是在某一属性的后边
当违约之后拒绝执行
5.4 完整性约束命名字句
格式:
constraint <完整性约束条件名>< 完整性约束条件>
完整性约束条件包括: not null unique primary key check foreign reference 等等
例:
sage char(3);
constraint C1 check(sage<30);
constraint studentkey primary key(sno);
这样做有什么意义呢?
这样做方便维护,当后期想修改这个完整性约束的字句的时候,就可以先删除,再修改
例如:
ALTER TABLE student
DROP CONSTRAINT C1;
ALTER TABLE student
ADD CONSTRAINT C1 CHECK(sage<40);
5.5 域中的完整性限制
域是一组具有相同数据类型的值的集合
例:
CREATE DOMAIN GenderDomain CHAR(2)
CONSTRAINT GD CHECK(VALUE IN('男','女'));
//之后,在所有的性别后边的限制条件就可以加上:
Ssex GenderDomain;
这样就OK了
同理,想修改的话,
也是先用ALTER......DROP......
先删除GD这个条件限制
然后 ALTER......ADD......加上新的,就可以了
5.6断言
CREATE ASSERTION <断言名> <check字句>
所谓断言,就是创建一个快捷查询条件
CREATE ASSERTION test
CHECK(60>=ALL(select count(*)
FROM SC
GROUP by cno)
);
5.7触发器
定义:是用户定义再关系表上的一类由事件驱动的特殊过程
5.7.1 定义触发器:
格式:
CREATE TRIGGER<触发器名>
{BEFORE|AFTER}<触发事件>ON <表名>
REFERENCING NEW|OLD ROW AS<变量>
FOR EACH{ROW|STATEMENT}
[WHEN<触发条件>]<触发动作>
说明:
表的拥有者才可以在表上创建触发器
触发器名:
- 同一模式下,触发器名必须是唯一的,触发器名和表名必须在同一模式下
表名:
- 触发器只能定义在基本表上,不能定义在视图上
触发事件:
INSERT、DELETE 、UPDATE
这三个事件可以触发事件,也可以是这三个事件的组合或者是
UPDATE OF<触发列>
AFTER/BEFORE
表示触发时机ALTER
触发事件操作执行之后激活触发器BEFORE
表示操作执行之前激活触发器
触发器类型
行级触发器:
FOR EACH ROW
语句级触发器:
FOR EACH STATEMENT
触发条件:当
WHEN
触发条件为真时,才执行触发动作,如果没有触发条件,则触发器激活后立即执行触发动作触发动作体
可以是一个匿名PL/SQL过程块(例2),也可以是对已创建存储过程的调用(例1)
行级触发器的话,用户可以用NEW和OLD引用新值和旧值
如果触发动作体执行失败,则激活触发器的事件(对数据库的增删改查)会终止执行
例1:当对表SC的Grade属性进行修改时,若分数增加了10%,则将此次操作记录到下表中
SC_U(Sno,Cno,Oldgrade,Newgrade)
行级触发器
CREATE TRIGGER SC_T
AFTER UPDATE OF Grade ON SC //当对SC表中Grade列进行修改后才出发下边的
REFERENCING
OLD row AS Oldtuple,//修改之前的数据和修改之后的数据赋予两个变量
NEW row as newtuple
FOR EACH ROW//行级触发器,每次Grade更新都触发下边的语句
WHEN(NewTuple.grade>=1.1*Oldtuple.grade)
INSERT INTO SC_U
VALUES(Oldtuple.sno,Oldtuple.cno,Oldtuple.grade,Newtuple.grade)
例2:教授工资不得低于4000,如果低于4000,则自动改为4000
CREATE TRIGGER TEST
BEFORE INSERT OR UPDATE ON teacher_table
REFERENCING NEW row as newtuple
FOR EACHE ROW
BEGIN //PL/SQL过程块
IF(newtuple.job=='教授')AND(newtuple.sal<4000)
THEN newtuple:=4000
END IF;
END;
5.7.2激活触发器
当数据表中有多个触发器:遵循以下顺序:
BEFORE
SQL语句
AFTER触发器
当有多个相同类型的触发器,遵循谁先创建谁先执行的原则
5.7.3删除触发器
DROP TRIGGER<触发器名><表名>