ch26 数据库完整性

用户定义的完整性:not null``unique 数据类型的定义、域的定义
将一张大表拆分成两张表(性能要求):检查两张表的属性
image.png

  1. 如果数据库不进行检查,则共享数据库时,会出错。Api甲的接口检查不完备,会导致Api乙接口取到的数据不完备。
  2. 具有共性(在不同应用域中都要进行检查)的数据中数据库中进行检查
    1. 学号 – 和学生紧密相关。不论在哪个应用域使用和学生有关的数据,都需要检查学号 — 所以可以做数据库中检查
    2. 不挂科(在奖学金评比的应用域中) – 则不是在数据库中进行检查,而是在特定的应用域中检查
  3. 当前完整性检查,哪些数据是和主体本质相关的,哪些数据是和应用域相关的

完整性 VS 安全性

image.png

完整性机制

image.png
事务提交:要么all,要么nothing

ch27 实体完整性

关系模型的实体完整性CREATE TABLE中用PRIMARY KEY定义

  • 单属性构成的码有两种说明方法
    • 定义为列级约束条件
    • 定义为表级约束条件
  • 对多个属性构成的码只有一种说明方法
    • 定义为表级约束条件

image.png

实体完整性检查

插入或对主码列进行更新操作时,关系数据库管理系统按照实体完整性规则自动进行检查。包括:

  • 检查主码值是否唯一,如果不唯一则拒绝插入或修改
  • 检查主码的各个属性是否为空,只要有一个为空就拒绝插入或修改

全表扫描

image.png

索引

image.png

ch28 参照完整性

关系模型的参照完整性定义

  • 在CREATE TABLE中用FOREIGN KEY 短语定义哪些列为外码
  • 用REFERENCES 短语指明这些外码参照哪些表的主码。

意义:
现实世界中的实体之间往往存在着某种联系,在关系模型中,实体以及实体之间的联系都是用关系来表示的,这样就自然存在着关系与关系之间的引用
参照完整性就是描述实体之间的联系的,一般是指多个实体或关系之间的关联关系
image.png
SC:选修记录

参照完整性检查

一个参照完整性将两个表中的相应元组联系起来
对被参照表和参照表进行增删改操作时有可能破坏参照完整性,必须进行检查
例如,对表SC和Student有四种可能破坏参照完整性的情况 :

  • SC表中增加一个元组,该元组的Sno属性的值在表Student中找不到一个元组,其Sno属性的值与之相等。
  • 修改SC表中的一个元组,修改后该元组的Sno属性的值在表Student中找不到一个元组,其Sno属性的值与之相等。
  • 从Student表中删除一个元组,造成SC表中某些元组的Sno属性的值在表Student中找不到一个元组,其Sno属性的值与之相等。
  • 修改Student表中一个元组的Sno属性,造成SC表中某些元组的Sno属性的值在表Student中找不到一个元组,其Sno属性的值与之相等 。

image.png
删除课程 – 学生的选修记录也为空

违约处理

在处理参照完整性,设为null时,需要小心是否会导致用户完整性、主体完整性的破坏
image.png
例如,有下面2个关系
学生(学号,姓名,性别,专业号,年龄) ,专业号是外码
专业(专业号,专业名)
假设专业表中某个元组被删除,专业号为12
按照设置为空值的策略,就要把学生表中专业号=12的所有元组的专业号设置为空值
**对应语义:某个专业删除了,该专业的所有学生专业未定,等待重新分配专业 **
参照主体出问题时,没有特别的语义
image.png

外码空值问题

这里讲解一下外码能否接受空值的问题。
外码变成空值

  • 是否符合现实的语义
  • 是否是作为主属性

例如,学生表中“专业号”是外码,按照应用的实际情况可以取空值,表示这个学生的专业尚未确定。但在学生一选课数据库中,关系Student为被参照关系,其主码为Sno;SC为参照关系,Sno为外码,它能否取空值呢?答案是否定的。因为Sno为SC的主属性,按照实体完整性Sno不能为空值。若SC的Sno为空值,则语义是:表明尚不存在的某个学生,或者某个不知学号的学生,选修了某门课程,其成绩记录在 Grade列中。这与学校的应用环境是不相符的,因此SC的Sno列不能取空值。同样,SC的 Cno是外码,也是SC(书中有错) Course的主属性,也不能取空值,因为语义会变为:学生选了一门课程,但是该课程没有课程号
因此对于参照完整性,除了应该定义外码,还应定义外码列是否允许空值。
一般地,当对参照表和被参照表的操作违反了参照完整性时,系统选用默认策略,即拒绝执行。如果想让系统采用其他策略则必须在创建参照表时显式地加以说明。
但,外码也是可以为空值的
外码可以为空,但只能在参照表里为空
举个栗子
学生(学生号,专业号)专业号是外码
专业(专业名,专业号)专业号是主码
在《学生》关系中,语义上:专业号为空表示还未给该学生分配专业。
但是!
在《专业》关系中,专业号不能为空(实体完整性)

ch29 用户定义的完整性

  • 属性的约束:只涉及到单一属性 – 年龄:18-35、检测住址是否合法
  • 元组的约束:涉及到不同属性的约束 – 男生不能住在4栋、检测住址和身份证号是否对应

体现的是:数据之间相互约束,体现的是一般性,而不是特殊性。特殊性的约束要交给应用程序自身
image.png
拒绝执行:是因为数据库无法对不同的错误进行统一的处理。男生住在4栋:是性别不对还是地址不对。

属性上的约束

列值非空

数据类型的检查:可以看做是属性上的约束,但是非常粗糙
例如:对年龄进行char类型的限制
image.png

列值唯一

image.png

条件表达式

image.png
char是单字节还是双字节,在不同数据库中有不同的定义
image.png

元组上的约束

涉及:非常多的属性
image.png

完整性约束命名子句

image.png

image.png

image.png

ch30 断言

  1. 涉及到的是多个表的完整性约束
  2. 不是所有的数据库都支持。相对来说比较麻烦
  3. 表现的业务逻辑有限

image.png
例子:
image.png

  1. group by可以接多个参数,按照一一组合的方式进行分组
  2. all表示遍历所有,每一个都必须满足相关条件
  3. 在执行相应语句时,会检查断言是否成立

ch31 触发器

触发器(trigger)是用户定义在关系表上的一类由事件驱动的特殊过程。一旦定义,触发器将被保存在数据库服务器中。任何用户对表的增、删、改操作均由服务器自动激活相应的触发器,在关系数据库管理系统核心层进行集中的完整性控制。触发器类似于约束,但是比约束更加灵活,可以实施更为复杂的检查和操作,具有更精细和更强大的数据控制能力。

面向过程的
变量可以在触发条件、触发动作体中使用
image.png

  • 尖括号(< >)表示必须填写的内容,如<触发器名>、<触发事件>、<表名>等。
  • 大括号({ })表示必须从其中选择一个选项,如{BEFORE | AFTER}、{ROW | STATEMENT}等。
  • 中括号([ ])表示可选的内容,如[WHEN <触发条件>]等。

慎用
all or nothing特性

组成

  1. 只有表的拥有者,即创建表的用户才可以在表上创建触发器,并且一个表上只能创建一定数量的触发器。触发器的具体数量由具体的关系数据库管理系统在设计时确定。
  2. 触发器名

触发器名可以包含模式名,也可以不包含模式名。同一模式下,触发器名必须是唯一的,并且触发器名和表名必须在同一模式下。

  1. 表名

触发器只能定义在基本表上,不能定义在视图上。当基本表的数据发生变化时,将激活定义在该表上相应触发事件的触发器,因此该表也称为触发器的目标表

  1. 触发事件

触发事件可以是 INSERT、DELETE 或 UPDATE,也可以是这几个事件的组合,如INSERT OR DELETE等,还可以是UPDATE OF <触发列,…>,即进一步指明修改哪些列时激活触发器。AFTER/BEFORE是触发的时机。AFTER表示在触发事件的操作执行之后激活触发器;BEFORE表示在触发事件的操作执行之前激活触发器。

  1. 触发器类型

触发器按照所触发动作的间隔尺寸可以分为行级触发器(FOR EACH ROW)和语句级触发器(FOR EACH STATEMENT)。

  1. 触发条件

触发器被激活时,只有当触发条件为真时触发动作体才执行;否则触发动作体不执行。如果省略WHEN触发条件,则触发动作体在触发器激活后立即执行

  1. 触发动作体

触发动作体可以是一个匿名PL/SQL过程块 也可以是对已创建存储过程的调用
如果是行级触发器,用户都可以在过程体中使用NEW和OLD引用事件之后的新值和事件之前的旧值
如果是语句级触发器,则不能在触发动作体中使用NEW ROW或OLD ROW进行引用,如果触发动作体执行失败,激活触发器的事件就会终止执行,触发器的目标表或触发器可能影响的其他对象不发生任何变化
image.png
语句级触发器是指一条SQL语句触发一次;
image.png
行级触发器是指一条SQL语句影响的每一行触发一次。
image.png
业务逻辑:修改分数不能提高太多

  1. 是某一个应用中特有的,如果只是本科生的教务处有限制,研究生院不是这样的限制,则不能在触发器中完成
  2. 整个大学有规定所有成绩修改增幅不能超过规定,可以使用触发器,将相关数据放在对应表中

本应该在应用中完成的,都在触发器中完成了。

  1. 减少了网络之间的交互和数据传输,有可能性能变好了
  2. 但是如果数据库是和别人共享的
    1. 别人使用相关表时,可能无意识的导致触发器
    2. 使用before操作,进行限制,会导致其他使用者插入数据(如1.1倍分数时)被拒绝,对语义有所影响
    3. 相当于在数据库中加入了一个公共的业务逻辑,但是不一定被其他使用者所接受

激活触发器

image.png

删除触发器

image.png