4-2数据库完整性

数据库的完整性

  • 数据的正确性
    • 是指数据符合现实世界语义,反应了当前的实际状况的
  • 数据的相容性
    • 是指数据库统一对象在不同的关系表中的数据是符合逻辑的,例如
      • 学生的学号必须唯一
      • 性别只有男和女
      • 本科生的年龄的取值范围是14-50
  • 数据的完整性和安全性是两个不同的概念
    • 数据的完整性
      • 防止数据库中存在不和语义的、不正确定数据
      • 方法对象:不合语义的、不正确的数据
    • 数据安全性
      • 保护数据库防止恶意破坏和非法存取
      • 方法对象:非法用户和非法操作

断言

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

创建断言的格式

create assertion <断言名> 
<check 子句>

[例5.18] 限制数据库课程最多60名学生选修

create assertion asse_sc_db_num
check (
    60>= (
        select count(*)
        from sc natural join (
            select cno
            from course
            where cname='数据库'
        )
    )
)

[例5.19] 限制每一门课程最多60名学生选修

create assertion asse_sc_cnum1
check(
    60 >= all(
        select count(*)
        from sc
        group by cno
    )
)

[例5.20] 限制每个学期每一门课程最多60名学生选修首先需要修改SC表的模式,增加个“学期(TERM)”属性 ALTER TABLE SC ADD TERM DATE;

create assertion ass_sc_cnum2
check (
    60>= all(
        select coutn(*)
        from sc
        group by cno, term
    )
)

删除断言

drop assertion <断言名>

触发器

触发器(Trigger)是用户定义在关系表上的一类由事件驱动的特殊过程

  • 触发器保存在数据库服务器中
  • 任何用户对表的增、删、改操作均由服务器自动激活相应的触发器
  • 触发器可以实施更为复杂的检查和操作,具有更精细和更强大的数据控制能力

定义触发器

create trigger<触发器名>
{before | afterr}<触发事件>
on <表名>
referecing new|old row as <变量>
for each {row|statement}
[when <触发条件>] <触发动作体>

定义触发器的语法说明

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

  • 触发器名

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

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

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

  • 表名

    • 触发器只能定义在基本表上,不能定义在视图上
    • 当基本表的数据发生变化时,将激活定义在该表上相应触发事件的触发器
  • 触发事件

    • 触发事件可以是INSERTDELETEUPDATE也可以是这几个事件的组合
    • 还可以UPDATE OF<触发列,...>,即进一步指明修改哪些列时激活触发器
    • AFTER/BEFORE是触发的时机
      • AFTER表示在触发事件的操作执行之后激活触发器
      • BEFORE表示在触发事件的操作执行之前激活触发器
  • 触发器类型

    • 行级触发器(FOR EACH ROW)每一行执行一次
    • 语句级触发器(FOR EACH STATEMENT)执行完该语句后,触发动作只发生一次
  • 触发条件

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

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

[例5.21] 当对表SC的Grade属性进行修改时,则将此次操作记录到下面表中:

SC_1(Sno,Cno,OldGrade,NewGrade)

其中OldGrade是修改前的分数,NewGrade是修改后的分数。

create or replace trigger sc_t
after update or delete
on sc
for each row
begin
	insert into sc1(sno, cno, oldGrade, newGrade)
	values(:old.sno, :old.cno, :old.grade, :new grade);
end;

[例5.22] 将每次对表Student的插入操作所增加的学生个数记录到表StudentInsertLog中。

create or replace trigger student_coutn
after insert
on student
begin
	insert into StudentInsertLog(Numbers)
	select count(*) from student;
end;

[例5.23] 定义一个BEFORE行级触发器,为教师表Teacher定义完整性规则“教授的工资不得低于4000元,如果低于4000元,自动改为4000元”。

create or replace trigger Insert_or_update_sal
before insert or update
on emp
for each row
begin
	if(:new.job = '教授') and (:new.sal < 4000) then
		:new.sal = 4000;
	end if;
end;

删除触发器

drop trigger <触发器名> 
on <表名>

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