Skip to content
Self-Knowing

第五章 数据库完整性

约 689 个字 50 行代码 预计阅读时间 3 分钟

数据的完整性是指:数据的正确性和相容性。

数据库在完整性方面的功能

  • 完整性约束条件的机制
  • 完整性检查的方法:在 insert,update,delete 后执行检查。
  • 违约处理:拒绝,级连,设空值

实体完整性

设置主码,让每条记录相互区分。

  • 主码有多个属性:只能在表级定义主码

完整性检查

  • 检查主码值是否为唯一:全表扫描/B+树索引。
  • 检查主码的各个属性是否为空

参照完整性

外码跟另一个表的主码保持对应。

参照完整性违约处理规则

  • 拒绝(NO ACTION)执行
  • 级联(CASCADE)操作
  • 设置为空值(SET- NULL)

image-20240307164641330

用户定义的完整性

CREATE TABLE时定义属性上的约束条件

  • 列值非空(NOT NULL)
  • 列值唯一(UNIQUE)
  • 检查列值是否满足一个条件表达式(CHECK)

元组上的约束条件检查和违约处理

  • 插入元组或修改属性的值时,关系数据库管理系统检查元组上的约束条件是否被满足
  • 如果不满足则操作被拒绝执行

完整性约束子句

格式

constraint <约束条件名> <约束条件>

显式的设置约束条件的姓名。

例句
create table Student
(
    Sno numeric(5),
    # Sname Char(20) not null, 这两句等价
    Sname Char(20) constraint C2 not null,
)

修改

先删除原来的约束条件,在增加新的约束条件

域的完整性约束

域是一组具有相同数据类型的值的集合,即属性的取值范围。

格式

建立一个性别域 GenderDomain ,并对其中的限制命名

create domain GenderDomain Char(2)
constrint GD check(value in('男', '女');

删除域 GenderDomain 的限制条件 GD

alter domain GenderDomain
drop constraint GD

断言

格式

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

每个断言都被赋予一个名字, 中的约束条件与 where 子句的条件表达式类似

【例题一】限制每一门课程最多 60名学生选修。

create assertion ASSE_SC_CNUM1
check (
    60 > = all (select counot * from SC gropu by Cno)
);

触发器

触发器:用户定义在关系表上的一类由时间驱动的特殊过程。

  • 又叫作:事件-条件-动作

格式

create trigger <触发器名>
[before | after] <触发事件> on <表名>
referencing new|old row as <变量>
for each {row | statement}
[when <触发条件>] <触发动作体>
  1. 表的拥有者在能在表上创建触发器
  2. 只能定义在基本表上
  3. 触发条件:insert, delete, update
  4. 触发的时机:after 和before
  5. 触发器类型:行级(for each row)和 语句级(for each statement
  6. 触发动作体:如果是行级触发器,用户都可以在过程体中使用NEW和OLD引用事件之后的新值和事件之前的旧值

【例题一】当对表SC的 Grade 属性进行修改时,若分数增加了 \(10\%\) 则将此次操作记录到下面表中:SC_U(Sno,Cno,Oldgrade,Newgrade),其中Oldgrade是修改前的分数,Newgrade是修改后的分数。

create trigger SC_T
after update of Grade on SC
referencing 
    old row as OldTuple
    new row as NewTuple
for each row
when (NewTuple.Grade > = 1.1 * OldTuple.Grade)
    insert into SC_U values(OldTuple.Sno,OldTuple.Cno,OldTuple.Gradem,NewTuple.Grade)

【例题二】将每次对表 Student 的插入操作所增加的学生个数记录到StudentInsertLog 中。

# 把新插入的数据保存到 DELTA 
create trigger Student_Count
after insert on Student
referencing
    new table as DELTA
for each statement
    insert into StudentInsertLog(Numbers)
    select count(*) from delta

激活触发器

多个触发器的顺序

  1. before 触发器
  2. 激活触发器的sql 语句
  3. after 触发器

删除触发器

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

Created: April 24, 2026
Last update: April 24, 2026

Discussion