利用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;