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