数据库完整性(实体完整性、参照完整性、用户定义的完整性、完整性约束命名字句、断言、触发器)

数据库完整性:数据的正确性(是指数据是符合现实世界语义,反映了当前实际状况的)、数据的相容性(是指数据库同一对象在不同关系表中的数据是符合逻辑的)

数据的完整性 :

  1. 防止数据库中存在不符合语义的数据,也就是防止数据库中存在不正确的数据
  2. 防范对象:不合语义的、不正确的数据

完整性检查:(数据库管理系统中检查数据是否满足完整性约束条件的机制称为完整性检查。)

      一般在INSERT、UPDATE、DELETE语句执行后开始检查,也可以在事务提交时检查。

违约处理:

拒绝(NO ACTION)执行该操作

级连(CASCADE)执行其他操作

一、实体完整性

关系模型的实体完整性 (根据定义位置不同)

  • CREATE  TABLE中用PRIMARY KEY定义
  • 单属性构成的码有两种说明方法
  1. 定义为列级约束条件
  2. 定义为表级约束条件
  • 对多个属性构成的码只有一种说明方法
  1. 定义为表级约束条件

实体完整性检查和违约处理

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

包括:

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

二、参照完整性

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

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

eg:

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)                       /*在表级定义参照完整性*/            

 );

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

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

eg:(四种可能破坏的情况)

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

 

被参照表(例如Student)

 

参照表(例如SC)

 

违约处理

可能破坏参照完整性

    插入元组

拒绝

可能破坏参照完整性

    修改外码值

拒绝

删除元组

  可能破坏参照完整性

拒绝/级连删除/设置为空值

修改主码值

 可能破坏参照完整性

拒绝/级连修改/设置为空值

参照完整性违约处理

(1) 拒绝(NO ACTION)执行 不允许该操作执行。该策略一般设置为默认策略

(2) 级联(CASCADE)操作 当删除或修改被参照表(Student)的一个元组造成了与参照表(SC)的不一致,则删除或修改参照表中的所有造成不一致的元组

(3)设置为空值(SET-NULL) 当删除或修改被参照表的一个元组时造成了不一致,则将参照表中的所有造成不一致的元组的对应属性设置为空值。

三、用户定义的完整性

(针对某一具体应用的数据必须满足的语义要求)

属性上的约束条件

  • 列值非空(NOT NULL) 、

eg: CREATE TABLE SC         (  Sno CHAR(9)  NOT NULL,    .......);   ##若有表级定义的主属性则默认非空。

  • 列值唯一(UNIQUE)

eg:

CREATE TABLE DEPT         (   Deptno  NUMERIC(2),             Dname  CHAR(9)   UNIQUE NOT NULL,                                     /*要求Dname列值唯一, 并且不能取空值*/           ..............         );

  • 检查列值是否满足一个条件表达式(CHECK)

 eg:      Ssex  CHAR(2)  CHECK (Ssex IN (‘男’,’女’))                                   /*性别属性Ssex只允许取'男'或'女' */

            Grade   SMALLINT CHECK (Grade>=0 AND Grade <=100),                  /*Grade取值范围是0到100*/

元组上的约束条件

(用CHECK短语定义元组上的约束条件,即元组级的限制)

同属性值限制相比,元组级的限制可以设置不同属性之间的取值的相互约束条件

 CHECK (Ssex='女' OR Sname NOT LIKE 'Ms.%')                    /*定义了元组中Sname和 Ssex两个属性值之间的约束条件*/

四、完整性约束命名子句

CONSTRAINT <完整性约束条件名><完整性约束条件>

  • <完整性约束条件>包括NOT NULL、UNIQUE、PRIMARY KEY短语、FOREIGN KEY短语、CHECK短语等

eg:建立学生登记表Student,要求学号在90000~99999之间,姓名不能取空值,年龄小于30,性别只能是“男”或“女”。

CREATE TABLE Student      

(   Sno  NUMERIC(6)      

         CONSTRAINT C1 CHECK (Sno BETWEEN 90000 AND 99999),      

    Sname  CHAR(20)        

        CONSTRAINT C2 NOT NULL,    

    Sage  NUMERIC(3)      

        CONSTRAINT C3 CHECK (Sage < 30),        

    Ssex  CHAR(2)          

       CONSTRAINT C4 CHECK (Ssex IN ( ‘男’,'女')),          

       CONSTRAINT StudentKey PRIMARY KEY(Sno)  ) ;           ###在Student表上建立了5个约束条件,包括主码约束(命名为StudentKey)以及C1、C2、C3、C4四个列级约束。

使用ALTER TABLE语句修改表中的完整性限制

eg:去掉上例Student表中对性别的限制。        

ALTER TABLE Student         DROP CONSTRAINT C4;

五、断言

  • 使用 CREATE ASSERTION语句,通过声明性断言来指定更具一般性的约束。
  • 可以定义涉及多个表的或聚集操作的比较复杂的完整性约束。
  • 断言创建以后,任何对断言中所涉及的关系的操作都会触发关系数据库管理系统对断言的检查,任何使断言不为真值的操作都会被拒绝执行

创建断言

CREATE ASSERTION<断言名>   ###中的约束条件与WHERE子句的条件表达式类似。

eg:限制数据结构课程最多20名学生选修

CREATE    ASSERTION    ASSE_SC_DB_NUM     ###断言名   

CHECK (20 >= (select count(*)                   /*此断言的谓词涉及聚集操作count的SQL语句*/               

         From Course,SC              ###多表 

         Where   SC.Cno=Course.Cno    and        Course.Cname ='数据结构')     );

删除断言

语句格式为 :DROP ASSERTION <断言名>;

如果断言很复杂,则系统在检测和维护断言的开销较高,这是在使用断言时应该注意的。

六、触发器

  • 触发器是用户定义在关系表上的一类由事件驱动的特殊过程  
  • 触发器保存在数据库服务器中
  • 任何用户对表的增、删、改操作均由服务器自动激活相应的触发器
  • 触发器可以实施更为复杂的检查和操作,具有更精细和更强大的数据控制能力

定义触发器

表的拥有者才可以在表上创建触发器

触发器只能定义在基本表上,不能定义在视图上

触发器名可以包含模式名,也可以不包含模式名

同一模式下,触发器名必须是唯一的

触发器名和表名必须在同一模式下

 CREATE TRIGGER <触发器名>                    ##触发事件发生,触发器被激活

 {BEFORE | AFTER} <触发事件> ON <表名>        ##触发器在事件前或后被激活

REFERENCING NEW|OLD ROW AS<变量>        ##指出引用的变量

FOR EACH  {ROW | STATEMENT}               ##行级触发器(FOR EACH ROW) 语句级触发器(FOR EACH STATEMENT)

 [WHEN <触发条件>]<触发动作体>

触发事件

  1. 触发事件可以是INSERT、DELETE或UPDATE也可以是这几个事件的组合
  2. 还可以UPDATE OF<触发列,...>,即进一步指明修改哪些列时激活触发器

触发器类型

  • 行级触发器(FOR EACH ROW)
  • 语句级触发器(FOR EACH STATEMENT)

eg:在例5.11的TEACHER表上创建一个AFTER UPDATE触发器,触发事件是UPDATE语句:

            UPDATE TEACHER SET Deptno=5;    

假设表TEACHER有1000行    

  • 如果是语句级触发器,那么执行完该语句后,触发动作只发生一次
  • 如果是行级触发器,触发动作将执行1000次

触发条件

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

触发动作体

  • 触发动作体可以是一个匿名PL/SQL过程块,也可以是对已创建存储过程的调用
  • 如果是行级触发器,用户都可以在过程体中使用NEW和OLD引用事件之后的新值和事件之前的旧值
  • 如果是语句级触发器,则不能在触发动作体中使用NEW或OLD进行引用 如果触发动作体执行失败,激活触发器的事件就会终止执行,触发器的目标表或触发器可能影响的其他对象不发生任何变化 

 

eg:     定义一个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;             

激活触发器

多个触发器时执行顺序规则

  • 执行该表上的BEFORE触发器;
  • 激活触发器的SQL语句;
  • 执行该表上的AFTER触发器。

删除触发器

删除触发器的SQL语法:      

DROP TRIGGER <触发器名> ON <表名>;

触发器必须是一个已经创建的触发器,并且只能由具有相应权限的用户删除。

 

 

 

学习自(数据库系统概论  第5版    -------王珊、萨师煊)

你可能感兴趣的:(数据库)