利用SQL语言实现数据库的动态完整性


1.动态约束的语法格式

  Integrity Constraint ::= (O, P, A, R)

  (1)O:需要定义

  (2)P:需要定义

  (3)A:需要定义

  (4)R:需要定义

2.触发器Trigger

  (1)Create Table 和 Trigger 的区分

    1)Create Table 是对单一列或单一元组的约束

    2)Trigger 实现动态约束以及多个元组之间的完整性约束

  (2)Trigger是一种过程完整性约束,Cteate Table是非过程约束

  (3)Trigger是一段程序,在特定的时刻自动触发进行,例如在更新操作前,或更新操作后

3.触发器Trigger的基本语法

    CREATE TRIGGER trigger_name  BEFORE | AFTER

      {INSERT | DELETE | UPDATE [ OF colname {, colname ...}] }

      ON tablename [REFERENCES corr_name_def {, cor_name_def ... }]  //在哪个表上操作

      [FOR EACH ROW | FOR EACH STATEMENT]  //对检索结果的每一行进行触发器操作;对SQL语句应用触发器

      [WHEN (search_condition)]  //检查条件,如果满足,执行下列语句

        { statement  //单行程序直接书写

        | BEGIN ATOMIC statement; { statement; ...} END }  //多行采用 Begin Atomic statement 方式

  (1)意义:当某一事件发生时(Before|After), 对该事件产生的结果(或是每一元组,或是整个操作的所有元组),检查条件 search_condition,如果满足条件,则执行后面的程序段。条件或程序段中引用的变量可用 corr_name_def 来限定

  (2)事件:BEFORE | AFTER {INSERT | DELETE | UPDATE ...}

    1)当一个事件 (Insert, Delete, 或Update) 发生之前 Before 或发生在之后 After 触发

    2)操作发生,执行触发器操作需处理两组值:更新前的值,更新后的值,这两个值由corr_name_def的使用来区分

    3)Before时刻表示还没有用新的值修改数据库的值,After表示修改了

  (3)corr_name_def的定义

    {OLD [ROW] [AS] old_row_corr_name   //更新前的旧元组命别名为

     | NEW [ROW] [AS] new_row_corr_name  //更新后的新元组命别名为

     | OLD TABLE [AS] old_table_corr_name  //更新前的旧Table命别名为

     | NEW TABLE [AS] new_table_corr_name  //更新后的新table命别名为

    }  //corr_name_def 将在检测条件(search_condition)后面的动作程序段中(search_condition下面的程序段中)被引用处理

4.触发器 Trigger示例

  (1)涉及一个触发器当进行 Teacher 表更新元组时,使其工资只能升不能降

    Create trigger teacher_chgsal before update of salary   //在更新前进行检测

      on Teacher

      references new x, old y

      for each row when(x.salary < y.salary)  //检测条件

        begin

      raise_application_error(-20003, 'invaslid salary on update');  //单行程序直接书写

        end;

  (2)假设 Student (S#, Sname, SumCourse),SumCourse 为该同学已学习课程的门数,初始值为0,以后每选修一门都要对其增1。设计一个触发器自动完成上述功能。

    Create trigger sumc after insert on sc  //新建触发器 sumc

      referencing new row newi  //新元组 newi

      for each row  //没有检测条件,任何条件下都为真

        begin

      update student set SumCourse = SumCourse + 1

      Where S# = :newi.S#;

        end;

  (3)假设 Student (S#, Sname, Sage, Ssex, Sclass)中某一学生要变更其主码 S# 的值,如使其原来的98030101变更为99030131,此时sc表中该同学已选课记录的S#也需自动随其改变。涉及一个触发器完成上述功能

    Create trigger updS#  after update of S# on Student  

      referencing old oldi, new newi

      for each row 

        begin

      update sc set S# = newi.S# where S# = :oldi.S#;

        end;

  (4)假设 Student(S#, Sname, SumCourse), 当删除某一个同学的S#时,该同学的所有选课也都要删除。设计一个触发器完成上述功能

    Create trigger delS# after delete on Student  //当Student有删除操作时,触发器会被触发

      reference old oldi

      for each row

        begin

      delete sc Where S# = :old.S#;

        end;

  (5)假设Student(S#, Sname, SumCourse), 当删除某一同学S#时,该同学的所有选课中的S#要置为空值。设计一个触发器完成上述功能

    Create trigger delS# after delete on Student 

      referencing old oldi

      for each now

        begin

      update sc set S# = NULL where S# = :oldi.S#;  //where S# =: oldi 的意思是该S# 的旧值是什么

        end;

  (6)假设Dept(D#, Dname, Dean), 而Dean一定是该系教师 Teacher(T#, Tname, D#, Salary)中工资最高的教师。设计一个触发器完成上述功能

    Create trigger upddean before update of Dean on Dept  //在更新之前进行检测

      referencing old oldi, new newi

      for each row when( dean not in (Select Tname from Teacher where D# = :newi.D#

           and Salary >= all(Select Salary from Teacher where D# = :newi.D#)) )

        begin

      raise_application_error(-20003, 'invalid Dean on update');

        end;

相关