【Oracle PL/SQL程序设计之触发器】触发器实验

【自治事务】

/**
*自治事务
* 能够保存出错信息-容许用户创建一个”事务中的事务”,可以独立与父事务提交或回滚
*可用于1.顶层匿名块 2.本地(过程当中的过程)、独立或打包的函数或者过程
3.对象数据类型的方法 4.数据库触发器
结束一个自治事务必须提交一个commit/rollback/执行DDL.
【使用缘由】
由于在数据库中某些状况若是发生异常了,那数据就会自动回滚,定义一个自治事务能够把异常信息保存下来,不会被回滚
*/程序员

insert into course values('11','aaaa',null,3);
commit;

select * from course;
delete from course where cno='11';
declare
       pragma autonomous_transaction; 
begin insert into course values('1112','滚尼玛',null,2);
       commit;
end;
rollback;

结果
这里写图片描述web



【触发器】

/**
若是必须访问变异表,则能够经过使用临时表,
或者一个PL/SQL容器,或者一个包变量绕过这些限制。
*/sql

/**
(3)、在学生-课程数据库中,学生表中有“平均成绩”列SAvgGrade,要求当对选课表SC 作insert(注
意特殊状况:插入的元组中成绩字段可能为null)、delete、update 修改时,系统自动修改学生表中平均
成绩。请编写触发器实现该业务,并设计案例加以测试。
*/数据库

–建立临时表

create global temporary table student_transaction ( sno char(9) )on commit delete rows;

–建立行级触发器

create or replace trigger t1_row after delete or insert or update on sc for each row declare begin if inserting then insert into student_transaction values(:new.sno);
   elsif deleting then
      insert into student_transaction values(:old.sno);
   else
      insert into student_transaction values(:old.sno);
      insert into student_transaction values(:new.sno);
   end if;
 dbms_output.put_line('插入成功');

end t1_row;

–建立表级触发器oracle

create or replace trigger t2_statement after delete or insert or update on sc declare cursor c is select distinct sno from student_transaction;
   avg1 number(3,0);
begin for i in c loop select avg(grade) into avg1 from sc where sno=i.sno;
       dbms_output.put_line('avg1 = '||avg1 ||'i.sno ='|| i.sno);
       update student set student.savggrade=avg1 where sno=i.sno;
  end loop;
end t2_statement;

SELECT * FROM course;
--INSERT INTO STUDENT(SNO,SNAME) VALUES('9512105','lh');
delete from sc where sno='9512105';
INSERT INTO SC VALUES('9512102','11',150);       --***问题这个位置把平均成绩打印不出来
COMMIT;
SELECT * FROM student_transaction;
SELECT * FROM STUDENT;

/**
(4)、在数据库中建立视图info_view,包含学生学号、姓名、课程号、课程名、成绩。该视图依赖于表
student、course 和sc,是不可更新视图。请编写替代触发器,当向视图中插入数据时分别向表student、
course 和sc 中插入数据,从而实现向视图插入数据的功能。
**【注意】**ORACLE 为行级触发器提供两个关联名NEW 和OLD,前者表明修改 以后的行,后者表明修改以前的行
newh和old关键字
*/svg

create or replace view info_view as select sno,sname,cno,cname,grade from student s natural join sc natural join course;

create or replace trigger TT instead of insert or update or delete on info_view REFERENCING NEW AS n --给:new关键字去一个别名 for each row --给以省略 declare begin -- IF INSERTING then insert into student(sno,sname) values(:n.sno,:n.sname);
     insert into course(cno,cname) values(:n.cno,:n.cname);
     insert into sc values(:n.sno, :n.cno, :n.grade);
end TT;


insert into info_view(sno,sname,cno,cname,grade) values('2015007','张飞','110','软件工程',500);
select sno,sname from student;
select cno,cname from course;

【说明】
这里在第(3)题还有一个问题遗留,就是经过查询sc表把平均成绩放大avg1变量中而后打印出来发现居然没有值,很纳闷,下次上课时候问问老师。
这里写图片描述
能够看出这里没有打印出avg1的值
这里写图片描述
问题解释:
这里写图片描述
发如今建立临时表时,咱们指定的sno字段长度是9,而在实际插入数据时,sql语句

这里写图片描述
能够发如今插入数据是咱们sno写的是7位数字,因此会自动补上两个空格,致使查找数据查找不到。函数

【触发器知识点】

触发器为了保证数据完整性
触发器定义:
触发器(trigger)是 提供给程序员和数据分析员来保证数据完整性的一种方法
,它是与表事件相关的特殊的存储过程
,它的执行不是由程序调用,也不是手工启动,而是由事件来触发,
触发器与存储过程的区别:
触发器与存储过程的惟一区别是触发器不能执行EXECUTE语句调用,
而是在用户执行Transact-SQL语句时自动触发执行。oop

1.触发事件

  • Event
    • 1.a DML statment
      insert update delete
    • 2.DDL
      create alter drop
    • 3.system/database event(如系统启动或者退出,异常)
    • 4.用户时间(登陆或者退出数据库)

2.触发时间:after/before

3.触发操做:触发器自己要作的事情,有触发器主题定义

4.触发频率:语句级(Statement)/行级(row)

5.触发器分类:

5.1与表关联的DML触发器,主要为业务实施使用。
            触发事件有DELETE,INSERT,UPDATE,MERGE
            分语句级触发器 和 行级触发器
    5.2与视图关联的instead of触发器
            只有行级触发器,以把对视图的操做转移给基表。
    5.3与SCHEMA关联的DDL触发器。
    5.4与SCHEMA、数据库关联的系统触发器。

这里写图片描述

这里写图片描述

【注意】

触发器与触发其的语句构成一个事务,除非使用自治事务,不然不能在触发器中出现DDL语句和事务处理语句 测试

  • 1.在触发器的执行部分只能用DML语句(SELECT、INSERT、UPDATE、 DELETE),不能使用DDL语句(CREATE、ALTER、DROP),
    不能包含事务控制语句(COMMIT,ROLLBACK,SAVEPOINT)。
  • 2.在触发器主体中调用的任何过程、函数,都不能使用事务控制语句。

参考文献ORACLE TRIGGER文档spa