源无极

导航

 
--01.什么是触发器
触发器是一个plsql程序,跟数据库中的表有关联,
当表中数据改变(update delete insert )的时,执行触发器程序。
为什么用触发器?
1.数据校验
2.备份数据
3.模仿mysql中自增
--02.如何使用触发器
语法:
create  or  replace  trigger 触发器名称
before | after --操作表之前或之后执行触发器
insert | update [of 字段名] | delete -- 执行插入 更新  删除 执行触发器(insert or update or delete )
on --在哪张表中执行触发器
--for each row 
declare
begin
   //........
end;
 
--03.向emp表中插入数据时,输出一句话(新员工入职了)
create or replace trigger tri_insert_emp
after
insert
on emp
declare
begin
  dbms_output.put_line('新员工入职了');
end;

 执行之后

 

 
--测试
insert into emp(empno,ename,sal) values(1,'老王',1000);
执行之后查看
 

--04.假如'2018/04/28'系统维护,不能修改emp表的数据

 

 

create or replace trigger tri1_emp
before --在改变表数据之前执行触发器
insert or update or delete
on emp
--for each row
declare
  v_sysdatestr varchar2(30); --定一个变量存放系统时间
begin
  --查询系统时间
  select to_char(sysdate,'yyyy/mm/dd') into v_sysdatestr from dual;
  if v_sysdatestr = '2018/04/28' then -- oracle中用= 跟java中==
    raise_application_error('-20009','系统维护,不能修改emp表的数据');
  end if;
end;

 

 执行

 

 

 尝试插入数据

insert into emp(empno,ename,sal) values(8,'老王',1000);

 

 

 同理
update
update emp set ename = '老王2' where empno = 1;
delete
delete from emp where empno = 1;
 
--04.触发器的真实使用(备份员工的工资)
在实际场景中如果需要添加这样的需求:在修改表的时候,要备份修改之前的数据

 

--建员工工资备份表
create table sal_log
(
       myid number(10) primary key,--主键id
       empno varchar2(30),--员工编号
       b_sal number(10),--员工修改前的工资
       a_sal number(10),--员工修改后的工资
       mydate date
);

 

--为sal_log表创建序列
create sequence seq_sal_log;
--创建触发器
 
create or replace trigger tri_sal_log
after
update of sal
on emp
for each row  --只要用到:new :old 把for each row放开
declare
begin
  --当更新emp表中sal字段 ,往sal_log表插入日志记录
  insert into sal_log values(seq_sal_log.nextval,:old.empno,:old.sal,:new.sal,sysdate);//  old.empno可以写成new.empno,反正这个不修改
end;

 

 

--oracle中的内置对象
          :new           :old --伪记录 
insert   新插入的记录         null
update   更新后的记录     更新前的记录
delete    null           删除前的记录
 
 
 --测试
 

执行

update emp set sal = 800 where empno = 2;

 

emp表

sal_log表

 

 疑问?如果修改名字,sal_log表数据改变吗

update  emp  set  ename = '小王' where empno = 1;
commit;
 结果是不会,因为我们只是修改了薪水的触发器
 
--删除触发器
drop trigger tri_emp;
 
 
--05.模拟msql主键自动增长
--测试表
create table t_test
(
       myid number(10) primary key,
       myname varchar2(30)
);
--创建一个触发器解决id自增
create  or   replace  trigger  tri_t_test
before
insert
on  t_test
for each row
declare
begin
  select seq_sal_log.nextval into :new.myid from dual;
end;
--测试
insert into t_test(myname) values('小王2');
commit;
select * from t_test;
 
--05.华为的面试题,高效的删除重复的数据
--创建表
create table t_test2
(
       myid number(10),
       myname varchar2(30)
);
--插入重复的数据
insert into t_test2 values(1,'小王1');
commit;
insert into t_test2 values(2,'小王2');
commit;
truncate table t_test2;--清空数据
高效删除重复数据方式一(子查询):
---查询
select rowid,t.* from t_test2 t;
--查询最小rowid
select t.*,min(rowid) from t_test2 t group by t.myid,t.myname;
select t.*,rowid from t_test2 t
--AAAM4WAAGAAAMC0AAA
--AAAM4WAAGAAAMC0AAD
--查询出需要删除的数据
select t.*,rowid from t_test2 t
where rowid not in (
select min(rowid) from t_test2 t group by t.myid,t.myname);
--删除重复数据
delete from t_test2 t
where rowid not in (
select min(rowid) from t_test2 t group by t.myid,t.myname);
--查询最终结果
select t.*,rowid from t_test2 t
高效删除重复数据方式二(多表关联查询):
--查询需要删除的重复数据
select t1.*,rowid from t_test2 t1
where rowid >(
select min(rowid) from t_test2 t2 where t2.myid = t1.myid and t2.myname = t1.myname )
 
--删除重复的数据
delete from t_test2 t1
where rowid >(
select min(rowid) from t_test2 t2 where t2.myid = t1.myid and t2.myname = t1.myname )
--查询最终结果
select t2.*,rowid from t_test2 t2
 
posted on 2019-03-03 00:16  源无极  阅读(85)  评论(0编辑  收藏  举报