数据库第四篇

发布于 2021-10-15  384 次阅读


        明天就是数据库的实验课,还有预习报告没有写,所以决定直接从之前文章复制粘贴,这篇文继续写上次第五章没写完的部分。(而且今天又小凤凰的三场比赛,真揪心啊~)

        上次写到了实体的完整性,这次接着写完整性。

  • 参照完整性:关系模型的参照完整性在create table时用foreign key来定义哪些列是外码,使用references来指明外码参照的主码
## 定义参照完整性实例
create table SC(
Sno char(10) 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));
  • 参照完整性检查和违约处理:这一部分就用一个表格来表示吧,对参照表进行增改时可能会破坏被参照表的完整性,默认在执行该操作时会报错。对被参照表进行删改时,会对参照表的完整性造成破坏,违约处理就是拒绝删除从而报错,或者设定为级联操作后级联更新。以下一个表格就可以说明问题。
被参照表(student)参照表(SC)违约处理
可能破坏参照完整性插入元组拒绝
可能破坏参照完整性 修改外码值拒绝
删除元组 可能破坏参照完整性 拒绝 /级联删除/设置为空值
删除主码值 可能破坏参照完整性 拒绝 /级联删除/设置为空值
## 举例说明
## 如果SC表中插入了student表中没有的学生,会有报错如下
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`student_course`.`sc`, CONSTRAINT `sc_ibfk_1` FOREIGN KEY (`Sno`) REFERENCES `student` (`Sno`))
## 如果删除student表中的学生时,没有设置级联删除,而SC表中有该学生的成绩,会有报错
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`student_course`.`sc`, CONSTRAINT `sc_ibfk_1` FOREIGN KEY (`Sno`) REFERENCES `student` (`Sno`))
## 设置级联删除,一定要注意应该在参照表中设置级联而不是在被参照表中设置
create table SC(
Sno char(10) not null,
Cno char(4) not null,
Grade smallint,
primary key(Sno,Cno),
foreign key(Sno) references Student(Sno) on delete cascade on update cascade,/*当删除或更新Student中的元组时,级联删除SC表中的元组*/
foreign key(Cno) references Course(Cno) on delete no action on update cascade);
  • 用户定义的完整性:针对某一具体应用数据必须满足的语义要求。违约处理:不满足则拒绝处理。
    • 属性上的约束条件的定义
      • 列值非空,not null
      • 列值唯一,unique
      • 检查列值是由满足一个条件表达式,check
    • 元组上的约束条件
      • 在create table 语句中可以使用check短语定义元组上的约束条件
## 直接上例子,几个完整性约束混合在一起了
create table dept(
Deptno smallint check (Deptno>=0 and Deptno<=100),
Dname char(9) not null unique,
Location char(1) check(Location in ('1','2')));
## 如果符合check则会插入,不符合则会报错,不符合Deptno>=0 and Deptno<=100报错如下
ERROR 3819 (HY000): Check constraint 'dept_chk_1' is violated.
## 不符合check(Location in ('1','2'),报错如下
ERROR 3819 (HY000): Check constraint 'dept_chk_2' is violated.
## 如果名字重复,报错如下
ERROR 1062 (23000): Duplicate entry 'zz' for key 'dept.Dname'
## 元组上的约束条件
create table S(
Ssex char(2),
Sname char(8),
check (Ssex='女' or Sname not like 'Ms.%'));
  • 完整性约束命名子句:sql提供完整性约束命名子句constraint。用法:constraint <完整性约束条件名><完整性约束条件>,完整性约束条件包括not null、unique、primary key 、check等,这里直接看例子
create table Student(
Sno smallint constraint C1 check(Sno between 90000 and 99999),
Sname char(10) constraint C2 not null,
Sage smallint constraint C3 check(Sage<30),
constraint StudentKey primary key(Sno));
## 使用alter table 修改表中的完整性限制
alter table Student drop constraint C1;
alter table Student add constraint C1 check (Sno between 10 and 100);
  • 断言:sql使用create assertion语句,通过声明性断言来指定更具一般性的约束。断言创建以后,任何对断言中所涉及关系的操作都会触发检查,任何使断言不为真值的操作都会被拒绝执行。但是我在实现的时候发现,mysql对于断言好像是不支持的,一直提示语法错误。
  • 触发器:触发器是用户定义在关系表上的一类由事件驱动的特殊过程。一旦定义,触发器被保存在数据库服务器中,任何用户对表的增删改操作均由服务器自动激活相应的触发器。触发器又叫做事件-条件-动作规则,当特定的系统事件发生时,对规则的条件进行检查,如果条件成立则执行规则中的动作。一般格式和示例下面给出:
create trigger <触发器名>
{after|before} <触发事件> on <表名>
referencing new|old row as <变量>
for each {row|statement}
[when <触发条件>] <触发动作体>
## 详细说明
1.只有表的拥有者才可以在表上创建触发器,并且触发器只能定义在基本表上,而不可以定义在视图上
2.触发器和表必须在同一模式(database)下
3.触发事件可以是insert,delete,update;也可以是几个事件的组合insert or delete,update of <触发列>。after/before是触发时机,表示是在触发事件之前还是之后
4.触发器类型:行级(for each row)和语句级(for each statement),具体就是如果是行级那么数据库每一行变化一次就执行一次;而语句级就是等整体执行完之后执行一次
5.触发条件,触发器被激活时,只有触发条件为真时触发动作体才执行否则不执行,如果没有when那么动作体立即执行
## 实例
create trigger sc_t
after update of Grade on sc /*当update sc表的Grade后,触发器激活*/
referencing oldrow as OldTuple,newrow as NewTuple
for each row /*行级触发*/
when(NewTuple.Grade>=1.1*OldTuple.Grade)/*当条件满足时执行insert否则不执行*/
insert into SC_u (Sno,Cno) value (OldTuple.Sno,OldTuple.Cno);
## 删除触发器
drop trigger <触发器名> on <表名>;

        啊~写一篇3000字的文也好累,寄,先到这里。