跳转至

七、数据库的完整性

数据库的完整性概述概述

  • 数据库的完整性
  • ==数据的正确性和相容性==
    • 防止数据库中存在不符合语义的数据,也就是防止数据库中存在不正确的数据
    • 防范对象:不合语义的、不正确的数据
  • 数据的安全性
  • 保护数据库防止恶意的破坏和非法的存取
  • 防范对象:非法用户和非法操作

  • 数据库的完整性是一种语义概念,

  • 防止数据库中存在
    • 不符合语义的数据,
    • 不正确的数据
  • 保证数据库中数据的质量。
  • 为维护数据库的完整性,DBMS必须:
  • 提供定义==完整性约束条件==的机制
  • 提供==完整性检查==的方法
  • ==违约==处理

完整性约束条件

  • (1) 列级约束
  • 主要是对属性的数据类型、数据格式和取值范围、精度等的约束。具体包括:

    • 对==数据类型==的约束,包括数据类型、长度、精度等的约束。例如学生姓名的数据类型是字符型,长度是8。
    • 对==数据格式==的约束,例如规定日期的格式为YYYY/MM/DD
    • 对==取值域==的约束,例如学生成绩的取值范围必须是0~100。
    • 对==空值==的约束
  • (2) 元组约束

  • 一个元组是由若干个属性组成的,元组级约束就是元组中各个属性之间的约束关系。例如订货关系中发货日期不能小于订货日期,发货量不得超过订货量等。
  • (3) 关系约束
  • 关系约束是指一个关系的各个元组之间、或者多个关系之间存在的各种联系或约束。常见的关系约束有实体完整性约束、参照完整性约束、函数依赖约束、统计约束等。

实现数据完整性的方法

  • 在关系数据库系统中,数据完整性控制策略包括规则、默认值、约束、触发器和存储过程等。

  • (1) 默认值

    • 如果在插入行中没有指定列的值,那么默认值指定列中所使用的值,例如:自动增长值,内置函数、数学表达式等
  • (2) 约束

    • 约束是自动强制数据完整性的方法。

    • 约束定义关系列中允许值的规则,是通用的强制完整性的标准机制。

    • 使用约束优于使用触发器、规则和默认值。

  • (3) 规则

    • 规则是大多数数据库系统中一个向后兼容的功能,用于执行一些与CHECK约束相同的功能。规则以单独的对象创建,然后绑定到列上。
  • (4) 触发器

    • 触发器是数据库系统中强制业务规则和数据完整性的主要机制
  • 声明式数据完整性👉通过声明保证数据完整性

  • 作为对象定义的一部分来定义数据必须达到的标准
  • DBMS 自动强制完整性
  • 通过使用==约束、默认和规则==来实现
  • 过程式数据完整性👉通过代码保证数据完整性
  • 在脚本中定义数据必须达到的标准
  • 在脚本中强制完整性
  • 通过使用==触发器==和==存储过程==来实现
  • 可在客户端或服务器用其他编程语言和工具来实现

实体完整性

  • 实体完整性规则规定:
  • ==主键的值不能取空值==
  • ==主键的值唯一==
  • 实现方法:通过对主键值的约束实现实体完整性。
  • 实体完整性的定义
  • 关系模型的实体完整性
    • CREATE TABLE中用PRIMARY KEY定义
  • ==单属性==构成的主键有两种说明方法
    • 定义为列级约束条件、定义为表级约束条件
  • 对==多个属性==构成的主键只有一种说明方法

    • 定义为表级约束条件
  • 定义表的主键后,每当对该表插入一条记录或者对主键进行更新操作时,DBMS自动进行实体完整性的检查

  • 检查主键是否唯一,
    • ==如果不唯一则拒绝进行插入或修改==;
  • 检查主键的各个属性(字段)值是否为空
    • ==如果有空的字段值,则拒绝操作==,从而保证实体完整性。

参照完整性

  • 参照完整性定义
  • 关系模型的参照完整性定义
    • 用FOREIGN KEY短语定义哪些列为外键,
    • 用REFERENCES短语指明外键参照哪些表的主键

判断题考过课本原话:参照完整性约束不仅存在于关系之间,同一个关系内部属性之间也会有参照约束关系。

【例 7‑6】定义SC中的参照完整性

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)    
);

主表与从表

  • 主表:指外键在另一张表中作主/候选键的表。(例中的班级表)
  • 从表:指含有外键的表,(例中的学生表)
班级表(主表) 学生表 (从表)
image-20230615113002823 image-20230615113031657

分析外键约束(主表👉从表)

  • 对主表进行三种操作,观察对表间完整性的影响:
  • 对主表中的主键进行操作
  • ==插入==:要求插入值满足主键限制即可,不影响其它表
  • ==修改==:可能会影响与该主键相关的从表的外键值。当相应的外键值存在时,有两个策略可用:
    • 一是改变对应从表的所有外键值,使之与主键一致;
    • 其二是不允许修改主表中的主键值。(反正就是不能改主表)
  • ==删除==:可能会影响与该主键相关的从表的外键值。若相应的外键值存在时,策略有二:

    • 一是不允许删除主表的主键值;
    • 二是级联删除从表中相应外键值所在的行。
  • 对从表中的外键操作

  • 插入:要求插入的外键值应“参照”(Reference)主表中的主键值。
  • 修改:要求修改的外键值“参照”主表中的主键值
  • 删除:不需要参照主表中的主键值。

参照完整性检查和违约处理

  • 参照关系中外键空值的问题
  • 需要定义外键是否允许为空值
  • 如果外键是其主键的组成部分,外键值不允许为空
  • 否则可以根据具体的语义确定外键值是否允许空值
  • ==在参照关系中插入==元组的问题(修改操作与之类似)
  • 受限插入
    • 向titles中插入新的元组,但该元组的pub_id属性值在表publishers中不存在,则系统拒绝
  • 级联(CASCADE)插入
    • 首先向被参照关系插入相应的元组,其主键值等于参照关系插入元组的外键值,然后再向参照关系插入该元组
  • 在被参照关系中删除元组的问题

  • 级联删除(CASCADES)

  • 受限删除(RESTRICTED)
  • ==置空值==删除

考题:当数据更新操作出现破坏参照完整性而使数据不一致时,系统可采用的策略有级联删除、受限删除和置空值

  • 这三种方法都保证了参照完整性约束,但具体哪种方法正确,取决于应用环境的语义,需要根据实际应用的业务规则决定具体的违约处理措施
  • 如果想让系统采用其他的策略则必须在创建表时显式地加以说明

触发器

  • 数据库系统一般提供两种主要机制来实现业务规则和数据完整性
  • 约束
    • 完整性约束机制在检测出违反约束条件的操作后,只能作==简单的动作==,例如,拒绝操作。
  • 触发器

    • 触发器是用户定义在关系数据表上的一类由事件驱动的==特殊过程==,用==编程==的方法实现复杂的业务规则
    • 触发器比约束更加==灵活==,可以实现一般的数据完整性约束实现不了的复杂的完整性约束,具有更精细和更强大的数据控制能力。
    • 触发器常常用于强制业务规则和数据完整性。
  • 触发器是一种特殊类型的存储过程,在对表或视图发出 UPDATE、INSERT 或 DELETE 语句时自动执行

  • 可用触发器完成很多数据库完整性保护的功能
  • 实现复杂的业务规则
  • 实现比CHECK 约束更复杂的数据完整性。
  • 比较数据修改前后的状态
  • 维护非规范化数据

  • SQL使用CREATE TRIGGER命令创建触发器,其一般格式为

CREATE TRIGGER <触发器名>  
     { BEFORE | AFTER} <触发事件> ON <表名>
        FOR EACH  {ROW | STATEMENT}
       [WHEN <触发条件>]
          <触发动作体>
  • 定义触发器的语法说明:

  • 创建者:表的拥有者

  • 触发器名,表名:触发器的目标表

  • 触发事件:INSERT、DELETE、UPDATE

  • 触发时间

    • BEFORE

    • 表示在==触发事件进行以前==,判断触发条件是否满足。

    • 若满足条件则先执行触发动作部分的操作,

    • 然后再执行触发事件的操作。

    • AFTER

    • 表示在==触发事件完成之后==,判断触发条件是否满足。

    • 若满足条件则执行触发动作部分的操作。

    • 如果触发事件因错误(如违反约束或语法错误)而失败,触发器将不会执行

  • 触发器类型

    • ==行级==触发器(FOR EACH ROW)。
    • 对每一个修改的元组都会触发触发器的检查和执行

    • ==语句级触发器(FOR EACH STATEMENT)。==

    • 只在SQL语句执行时候进行触发条件的检查和触发器的执行
  • 触发条件

    • 触发条件为真,省略WHEN触发条件
  • 触发动作体

    • 触发动作体是满足触发器条件后,执行的一系列数据库操作。

    • 如果触发动作体==执行失败==,激活触发器的事件就会终止执行,触发器的目标表或触发器可能影响的其他对象不发生任何变化

例如Teacher表上创建一个AFTER UPDATE触发器。如果表Teacher有1000行,执行如下语句:

UPDATE Teacher SET Deptno=5;
  • 如果该触发器为语句级触发器,那么执行完该语句后,触发动作只发生一次;
  • 如果是行级触发器,触发动作将执行1000次

SQL Server中的触发器

  • 用途
  • 在数据库中的相关表上==实现级联更改==
    • 引用完整性可以通过外键约束定义,但可使用触发器在级联更新或删除时确保采用适当的行为。
    • 若触发表上定义了约束,它们在触发器执行之前检查。若违反了约束,则触发器不执行
  • 强制比 CHECK 约束更复杂的数据完整性
  • 定义用户定制的错误信息
    • 通过使用触发器,可以在特定条件出现时调用预定义或动态定义的定制错误信息
    • 约束、规则和默认只能通过标准系统错误信息来表达错误。若需要定制信息或更复杂的错误处理,需要使用触发器
  • 维护非标准数据,特别是处理较为复杂的逻辑

  • 触发器与CHECK 约束

  • CHECK 约束只能根据逻辑表达式或==同一表中==的另一列来验证列值。
    • 如果应用程序要求根据另一个表中的列验证列值,则必须使用触发器。
  • 约束只能通过标准的系统错误信息传递错误信息。
    • 如果应用程序要求使用(或能从中获益)自定义信息和较为复杂的错误处理,则必须使用触发器
  • 触发器可以引用其它表中的列

    • 例如,触发器可以包含使用 Transact-SQL 代码的复杂处理逻辑。因此,触发器可以支持约束的所有功能;但并不总是最好的方法。
  • inserted表和deleted表

  • Inserted表
    • 存放insert或update语句执行过程中,插入到触发表中的新数据行的副本
    • inserted 表中的行是和触发表中的新数据行相同.
  • Deleted表
    • 存放delete 或update语句执行过程中,从触发表中删除的旧数据行的副本
    • deleted表和触发表不会有相同的行.
  • 触发操作完成后,与触发器相关的表被==自动删除掉==

【例 7‑9】创建限制更新数据的触发器,限制将SC表中不及格学生的成绩改为及格。

CREATE TRIGGER tri_grade
    ON SC FOR UPDATE
    AS 
        IF UPDATE (Grade)
             IF EXISTS (SELECT * FROM INSERTED JOIN DELETED 
              ON INSERTED.Sno = DELETED.Sno
        WHERE INSERTED.GRADE >= 60 AND DELETED.Grade < 60)
           BEGIN
               RAISERROR ('不允许将不及格学生的成绩改为及格!')
            ROLLBACK
           END