/**
*自治事务
* 可以保存出错信息-允许用户建立一个”事务中的事务”,能够独立与父事务提交或回滚
*可用于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
,前者代表修改 之后的行,后者代表修改之前的行
*/
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语句时自动触发执行。
5.1与表关联的DML触发器,主要为业务实施使用。 触发事件有DELETE,INSERT,UPDATE,MERGE 分语句级触发器 和 行级触发器 5.2与视图关联的instead of触发器 只有行级触发器,以把对视图的操作转移给基表。 5.3与SCHEMA关联的DDL触发器。 5.4与SCHEMA、数据库关联的系统触发器。
触发器与触发其的语句构成一个事务,除非使用自治事务,否则不能在触发器中出现DDL语句和事务处理语句
参考文献ORACLE TRIGGER文档