【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;

结果
这里写图片描述



【触发器】

/**
如果必须访问变异表,则可以通过使用临时表,
或者一个PL/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;

–创建表级触发器

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关键字
*/

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的值
这里写图片描述

【触发器知识点】

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

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文档

猜你喜欢

转载自blog.csdn.net/alearn_/article/details/80217361