数据库完整性
文章目录
- 5.1参照完整性
- 5.1.1实体完整性定义
- 5.1.2实体完整性的违约处理和检查
- 5.2参照完整性
- 5.2.1参照完整性定义
- 5.2.2参照完整性的违约处理和检查
- 5.3用户自定义的完整性
- 5.3.1属性上的约束条件
- 5.3.2元组上的约束条件
- 5.4完整性约束命名子句
- 5.5断言
- 5.7触发器
- 5.7.1定义触发器
- 5.7.2激活出发器
- 5.7.3删除触发器
集成环境:Microsoft SQL Server Management Studio 18
这个是指数据的正确性和数据的相容性。
为了数据库的完整性,数据库管理系统必须提供以下策略
- 提供定义定义完整性约束条件的机制
- 完整性约束条件也称为完整性规则,是数据库中的数据必须满足的语义约束条件
- SQL标准使用了一系列概念来描述完整性,包括关系模型的实体完整性、参照完整性和用户定义完整性
- 这些完整性一般由SQL的数据定义语言语句来实现
- 提供完整性检查方法
- 数据库管理 系统中检查数据是否满足完整性约束条件机制称为完整性检查
- 一般在 delete,update,insert语句后执行检查,也可以在事务提交后检查
- 违约处理
- 数据库管理系统若发现用户违背了数据库完整性约束条件就应该采取一定动作
- 拒绝(no action)执行该操作
- 级联(cascade)执行其他操作
本章主要内容
5.1参照完整性
5.1.1实体完整性定义
(1) 在列级定义主码
CREATE TABLE girlfriend
(stuname char(10) primary key,
girlfriendName char(10) NOT NULL,
girlfriendAge char(10),
girlfriendPhone int);
(2)在表级定义主码
CREATE TABLE girlfriend
(stuname char(10),
girlfriendName char(10) NOT NULL,
girlfriendAge char(10),
girlfriendPhone int
primary key(stuname));
5.1.2实体完整性的违约处理和检查
- **插入或对主码列进行更新操作时,**RDBMS按照实体完整性规则自动进行检查。包括:
- 检查主码值是否唯一,如果不唯一则拒绝插入或修改
- 检查主码的各个属性是否为空,只要有一个为空就拒绝插入或修改
检查主码是否唯一的一种办法是全表扫描,为了避免全表扫描,RDBMS核心一般在主码上自动建立索引
5.2参照完整性
5.2.1参照完整性定义
(1) 在表级定义参照完整性
将女朋友表中的学生名与学生表中的学生名相关连
CREATE TABLE girlfriend
(stuname nvarchar(50) primary key,
girlfriendName char(10) NOT NULL,
girlfriendAge char(10),
girlfriendPhone int,
foreign key(stuname) references [dbo].[Student](Sname) -- 在表级定义参照完整性
);
5.2.2参照完整性的违约处理和检查
一个参照完整性是将两个表中相应的元组联系起来,对参照表和被参照表进行增删改查操作时有可能破坏参照完整性,必须进行检查
被参照表(Student) | 参照表(girfriend) | 违约处理 |
可能破坏参照完整性 | 插入元组 | 拒绝 |
可能破坏参照完整性 | 修改外码值 | 拒绝 |
删除元组 | 可能破坏参照完整性 | 拒绝/级连删除/设置为空值 |
修改主码值 | 可能破坏参照完整性 | 拒绝/级连修改/设置为空值 |
参照完整性的违约处理
(1) 拒绝(no action)执行
- 不允许执行该操作,该策略一般是默认策略
(2)级联(CASCADE)操作
- 当删除或修改被参照表(Student)的一个元组造成了与参照表(SC)的不一致,则删除或修改参照表中的所有造成不一致的元组
(3)设置为空值(SET-NULL)
- 当删除或修改被参照表的一个元组时造成了不一致,则将参照表中的所有造成不一致的元组的对应属性设置为空值。
对于参照完整性,除了定义外码,还定义外码是否为空
显示处理参照完整性违约处理示例
(2)显示参照完整性的违约示例
CREATE TABLE girlfriend2
(stuname nvarchar(50) primary key,
girlfriendName char(10) NOT NULL,
girlfriendAge char(10),
girlfriendPhone int,
foreign key(stuname) references [dbo].[Student](Sname) -- 在表级定义参照完整性
ON DELETE CASCADE /*级联删除SC表中相应的元组*/
ON UPDATE CASCADE /*级联更新SC表中相应的元组*/
--ON DELETE NO ACTION
/*当删除course 表中的元组造成了与SC表不一致时拒绝删除*/
--ON UPDATE NO ACTION
/*当更新course表中的cno时,级联更新SC表中相应的元组*/
);
5.3用户自定义的完整性
5.3.1属性上的约束条件
create table 时定义属性上的约束条件
- 列值非空(not null)
- 列值唯一(unique)
- 检查列值是否满足一个表达式(check)
(1)列值空值
CREATE TABLE girlfriend
(stuname nvarchar(50),
girlfriendName char(10) NOT NULL,--列值非空
girlfriendAge char(10),
girlfriendPhone int
);
(2)列值唯一
CREATE TABLE girlfriend
(stuname nvarchar(50) UNIQUE,--列值唯一
girlfriendName char(10),
girlfriendAge char(10),
girlfriendPhone int UNIQUE,--列值唯一);
(3)check约束,对性别,年龄等约束;
CREATE TABLE girlfriend4
(stuname nvarchar(50),
girlfriendName char(10),
girlfriendSEX char(2) check(girlfriendSEX IN ('男','女')),--性别约束
girlfriendAge int check(girlfriendAge between 18 and 20) ---年龄约束
foreign key(stuname) references [dbo].[Student](Sname) -- 在表级定义参照完整性
);
属性上约束条件检查和违约处理
- 插入元组或修改属性的值时,关系数据库管理系统检查属性上的约束条件是否被满足
- 如果不满足则操作被拒绝执行
5.3.2元组上的约束条件
在CREATE TABLE时可以用CHECK短语定义元组上的约束条件,即元组级的限制
同属性值限制相比,元组级的限制可以设置不同属性之间的取值的相互约束条件
CREATE TABLE girlfriend0
(stuname nvarchar(50),
girlfriendName char(10),
girlfriendSex char(2),
girlfriendAge int check(girlfriendAge between 18 and 20),
girlfriendPhone int,
CHECK (girlfriendSex='女' OR girlfriendName NOT LIKE 'Ms.%')
/*定义了元组中Sname和 Ssex两个属性值之间的约束条件*/
);
性别是女性的元组都能通过该项检查,因为Ssex=‘女’成立;
当性别是男性时,要通过检查则名字一定不能以Ms.打头
元组上约束条件检查和违约处理
- 插入元组或修改属性的值时,关系数据库管理系统检查属性上的约束条件是否被满足
- 如果不满足则操作被拒绝执行
5.4完整性约束命名子句
(1)完整性约束命名子句
constraint <完整性约束条件名> <完整性约束条件>
CREATE TABLE girlfriend10
(stuname nvarchar(50) CONSTRAINT C1 NOT NULL,
girlfriendName char(10),
girlfriendSex char(2) CONSTRAINT C2 CHECK (girlfriendSex IN ( '男','女')),
girlfriendAge int CONSTRAINT C3 check(girlfriendAge between 18 and 20), girlfriendPhone int,
);
(2)删除约束
ALTER TABLE girlfriend10 DROP CONSTRAINT C1;
(3)修改约束
ALTER TABLE Student ADD CONSTRAINT C3 check(girlfriendAge between 8 and 30);
5.5断言
- sql中,可以使用create assertion语句,通过声明性断言来指定更具一般性的约束
- 可以定义涉及多个表或聚集操作的比较复杂的完整性约束。
- 断言创建以后,任何对断言中所涉及关系的操作都会触发关系数据库管理系统对断言的检查,任何使断言不为真值的操作都会被拒绝执行。
(1)定义断言
CREATE ASSERTION <断言名> <CHECK子句>
[例5.18] 限制数据库课程最多60名学生选修
CREATE ASSERTION ASSE_SC_DB_NUM
CHECK (60 >= (select count(*)
/*此断言的谓词涉及聚集操作count的SQL语句*/
From Course,SC
Where SC.Cno=Course.Cno and Course.Cname ='数据库')
);
(2)删除断言
DROP ASSERTION <断言名>;
如果断言很复杂,则系统在检测和维护断言上的开销较高,这是在使用断言时应该注意的。
5.7触发器
触发器(Trigger)是用户定义在关系表上一类事件驱动的特殊过程
- 触发器保存在数据库服务器中
- 任何用户对表的增删改查均有服务器自动激活相应的触发器
- 触发器可以实施更为复杂的检查和操作,具有更精致和更强大的数据控制能力
5.7.1定义触发器
CREATE TRIGGER语法格式
CREATE TRIGGER <触发器名>
{BEFORE | AFTER} <触发事件> ON <表名>
REFERENCING NEW|OLD ROW AS<变量>
FOR EACH {ROW | STATEMENT}
[WHEN <触发条件>]<触发动作体>
定义触发器语法说明
(1)拥有表的用户才可以定义触发器
(2) 触发器名
- 触发器名可以包括模式名,也可以不包括模式名
- 同一模式下触发器名必须唯一
- 触发器名和表必须在同一模式模式下
(3)表名
- 触发器只能定义在表上,不能定义在视图上
- 基本表发生变化时,将激活定义在该表上的触发器
(4)触发事件
- 触发事件可以是INSERT、DELETE或UPDATE
也可以是这几个事件的组合 - 还可以UPDATE OF<触发列,…>,即进一步指明修改哪些列时激活触发器
- AFTER/BEFORE是触发的时机
- AFTER表示在触发事件的操作执行之后激活触发器
- BEFORE表示在触发事件的操作执行之前激活触发器
(5)触发器类型
- 行级触发器(FOR EACH ROW)
- 语句级触发器(FOR EACH STATEMENT)
[例5.21]当对表SC的Grade属性进行修改时,若分数增加了10%则将此次操作记录到下面表中:
SC_U(Sno,Cno,Oldgrade,Newgrade)
其中Oldgrade是修改前的分数,Newgrade是修改后的分数。
CREATE TRIGGER SC_T
AFTER UPDATE OF Grade ON SC
REFERENCING
OLD row AS OldTuple,
NEW row AS NewTuple
FOR EACH ROW
WHEN (NewTuple.Grade >= 1.1*OldTuple.Grade)
INSERT INTO SC_U(Sno,Cno,OldGrade,NewGrade)
VALUES(OldTuple.Sno,OldTuple.Cno,OldTuple.Grade,NewTuple.Grade)
[例5.22] 将每次对表Student的插入操作所增加的学生个数记录到表StudentInsertLog中。
CREATE TRIGGER Student_Count
AFTER INSERT ON Student
/*指明触发器激活的时间是在执行INSERT后*/
REFERENCING
NEW TABLE AS DELTA
FOR EACH STATEMENT
/*语句级触发器, 即执行完INSERT语句后下面的触发动作体才执行一次*/
INSERT INTO StudentInsertLog (Numbers)
SELECT COUNT(*) FROM DELTA
[例5.23] 定义一个BEFORE行级触发器,为教师表Teacher定义完整性规则“教授的工资不得低于4000元,如果低于4000元,自动改为4000元”。
CREATE TRIGGER Insert_Or_Update_Sal
BEFORE INSERT OR UPDATE ON Teacher
/*触发事件是插入或更新操作*/
FOR EACH ROW /*行级触发器*/
BEGIN /*定义触发动作体,是PL/SQL过程块*/
IF (new.Job='教授') AND (new.Sal < 4000)
THEN new.Sal :=4000;
END IF;
END;
例子
(1)定义一个before级触发器
--创建insert update 触发器
create trigger Insert_Or_Update ON girlfriend
after insert,update
as begin
update girlfriend set girlfriendSalary = 100 where girlfriendSalary<100;
end
插入数据
insert into girlfriend([stuname],[girlfriendName],[girlfriendSalary],[girlfriendAge],[girlfriendPhone]) values('李勇','花花',10,14,12345);
insert into girlfriend([stuname],[girlfriendName],[girlfriendSalary],[girlfriendAge],[girlfriendPhone]) values('李2勇','花花1',101,14,12345);
insert into girlfriend([stuname],[girlfriendName],[girlfriendSalary],[girlfriendAge],[girlfriendPhone]) values('李3勇','花花2',15,14,12345);
5.7.2激活出发器
触发器的执行,是由触发事件激活的,并由数据库服务器自动执行
5.7.3删除触发器
删除触发器的SQL语法
DROP TRIGGER <触发器名> ON <表名>;
触发器必须是一个已经创建的触发器,并且只能由具有相应权限的用户删除。