/***********************触发器****************
触发器:
触发器分为 :before |after |instead of

语法:
create [or replace] trigger 触发器名称
before|after|instead of
insert [or] update [of 字段] [or] delete
on 表名或者试图名称
[for each row]----:new :old
[when 触发器条件]


触发器:行级触发器和语句级触发器
行级触发器::new ----将要添加的新数据
            :old ----即将要删除的数据
在insert数据可以使用 :new
在delete数据可以使用 :old
在update数据可以使用 :new :old           
               
注意:
1.在触发器中不能使用事务控制语句(commit rollback )
2.在语句级的触发器,不管影响数据条数是多少,仅仅只激活一次触发器
3.intead of触发器只能用在试图上
*************************************************/

-----当前有一张学生信息表 stuid stuname ,当每次删除数据,要求备份对应的数据

create table stuinfo
(
 stuid number(4) primary key,
 stuname varchar2(100)

)
insert into stuinfo values(1001,'张三');
insert into stuinfo values(1002,'李四');


---1.创建备份表,其结构与学生表相同
create table stuinfoback as select * from stuinfo where 1=2;
---2.创建触发器,完成当删除学生信息,向stuinfoback表插入数据
create or replace trigger tri_stuinfo
before delete on stuinfo
for each row
begin
  ---向stuinfoback表插入数据
  insert into stuinfoback values(:old.stuid,:old.stuname);
  commit;
end;

---测试
delete from stuinfo where stuid=1001

select * from stuinfo;
select * from stuinfoback;

-----当添加学生信息,备份表中也相应添加对应的数据,当我们修改学生,备份表中的信息也随之修改
create or replace trigger tri_stuinfo
after
insert or update of stuname or delete
on stuinfo
for each row
begin
   ----当添加学生信息
   if inserting then
     dbms_output.put_line('insert');
     insert into stuinfoback values(:new.stuid,:new.stuname);
   elsif updating then
   dbms_output.put_line('update');
     update stuinfoback set stuname=:new.stuname where stuid=:old.stuid;
   elsif deleting then
   dbms_output.put_line('delete');
     delete from stuinfoback where stuid =:old.stuid;
   end if;
end;

---测试
insert into stuinfo values(1003,'张飞');
insert into stuinfo values(1004,'关云长');

update stuinfo set stuname='kkkk' where stuid in(1003,1004);

delete from  stuinfo  where stuid in(1003,1004);

commit;


----语句级触发器
create or replace trigger tri_stu
after update
on stuinfo
begin
  dbms_output.put_line('语句级别触发器被调用');
end;

---有条件触发器
create or replace trigger tri_stuinfo
after
insert or update of stuname or delete
on stuinfo
for each row
---触发器的条件
when (new.stuid > 1005)---没有冒号
begin
   ----当添加学生信息
   if inserting then
     dbms_output.put_line('insert');
     insert into stuinfoback values(:new.stuid,:new.stuname);
   elsif updating then
   dbms_output.put_line('update');
     update stuinfoback set stuname=:new.stuname where stuid=:old.stuid;
   elsif deleting then
   dbms_output.put_line('delete');
     delete from stuinfoback where stuid =:old.stuid;
   end if;
end;

insert into stuinfo values(1006,'xiaoyi');

----学生信息表
create table stuinfo
(
 stuid number(4) primary key,
 stuname varchar2(100)

)
----学生成绩表
create table stuscore
(
 sid number(4) primary key,
 subject varchar2(100),
 stuid number(4) references stuinfo(stuid),
 score int
)

insert into stuscore values(1,'html',1001,90);
insert into stuscore values(2,'oracle',1001,100);
insert into stuscore values(3,'html',1002,80);
insert into stuscore values(4,'oracle',1002,60);

---创建试图 stuid stuname subject score
create or replace view v_stuinfo
as
select sid,stuinfo.stuid,stuname,subject,score from stuinfo
inner join stuscore on stuinfo.stuid=stuscore.stuid


select * from v_stuinfo;

---通过试图修改学生信息(不成功)
update v_stuinfo set stuname='kkk' where sid=1;
---通过学生信息表来修改学生信息(成功?)
update stuinfo set stuname='kkk' where stuid=1001;

create or replace trigger tri_v_stuinfo
instead of  update on v_stuinfo
for each row
begin
   update stuinfo set stuname=:new.stuname where stuid=:old.stuid;
end;


---触发器管理
---禁用
alter trigger tri_stuinfo disable;
---激活
alter trigger tri_stuinfo enable;


----自主性事务
--子存储过程
create or replace procedure pro_sub
is
 mysal emp.sal%type;
 ---自主事务声明
 --pragma autonomous_transaction;
begin
    select sal into mysal from emp where empno=7369;
    dbms_output.put_line('在子过程中:'||mysal);
    ---事务回滚
    rollback;
end;
 
----父存储过程
create or replace procedure pro_parent
is
 mysal emp.sal%type;
begin
     select sal into mysal from emp where empno=7369;
     dbms_output.put_line('修改之前:'||mysal);
     ---修改
     update emp set sal=888 where empno=7369;
     ---调用子存储过程
     pro_sub();
     select sal into mysal from emp where empno=7369;
      dbms_output.put_line('修改之后:'||mysal);
end;


--测试
begin
 pro_parent();
end;