触发器:在执行insert,updatedalete语句时,
触发执行的一段plsql代码sql
能够在sql语句执行前触发,也能够在sql语句执行后触发,
还能够替换原sql语句只执行触发器代码数据库
让触发器失效
alter trigger 触发器名 disable;
oracle
让触发器生效
alter trigger 触发器名 enable;
测试
删除触发器
drop trigger 触发器名;
日志
表级触发器:一个sql语句只会触发一次触发器代码code
语法rem
create trigger 触发器名称 before|alter insert[or delete[or update]] on 表名 begin end;
给emp建立一个触发器,当给emp表插入数据时,打印'插入数据'
新建t1触发器it
create trigger t1 before insert on emp begin dbms_output.put_line('插入数据'); end;
插入数据进行测试io
insert into emp(empno,ename,deptno) values(7123,'asd',10); rollback;
会输出table
插入数据
尝试插入多条数据
insert into emp(empno,ename,deptno) select 1234,'a',10 from dual union all select 2345,'b',10 from dual union all select 3456,'c',10 from dual; rollback;
输出
插入数据
发现插入多条数据时,也是打印了一次
触发器中的三个变量,用来区分insert,update,delete语句的
变量名称 | 描述 |
---|---|
inserting: | 布尔类型的变量,当insert语句触发触发器时,返回true,不然返回false |
updating: | 布尔类型变量,当update语句触发触发器时,返回true,不然返回false |
deleting: | 布尔类型变量,当delete语句触发触发器时,返回true,不然返回false |
新建触发器
create or replace trigger t1 before insert or update or delete on emp begin if inserting then dbms_output.put_line('插入数据'); end if; if updating then dbms_output.put_line('修改数据'); end if; if deleting then dbms_output.put_line('删除数据'); end if; end;
输入
update emp set ename='slzd' where empno=7777;
输出
修改数据
输入
delete emp where empno in (9123,7777);
输出
删除数据
行触发器:当表中一条数据改变时,触发一次触发器代码
语法
语法
create or replace trigger 触发器名 after|before insert [or update [or delete]] on 表名 for each row declare begin end;
建立触发器
create or replace trigger t1 before insert or update or delete on emp for each row begin if inserting then dbms_output.put_line('插入数据'); end if; if updating then dbms_output.put_line('插入数据'); end if; if deleting then dbms_output.put_line('删除数据'); end if; end;
插入一条数据
insert into emp(empno,ename,deptno) values(7123,'a',10);
输出
插入数据
插入多条数据
insert into emp(empno,ename,deptno) select 7123,'a',10 from dual union all select 7124,'b',10 from dual union all select 7125,'c',10 from dual;
输出
插入数据 插入数据 插入数据
删除多条数据
delete from emp where empno in (1011,9123);
输出
删除数据 删除数据
:old
获取到数据当前记录,修改以前的数据:new
获取修改后(即将要修改)的数据create or replace trigger t1 before update on dept for each row begin --打印修改前的数据 dbms_output.put_line(:old.deptno||' , '||:old.dname||' , '||:old.loc); --打印修改后的数据 dbms_output.put_line(:new.deptno||' , '||:new.dname||' , '||:new.loc); end;
修改一条记录
update dept set dname='aa',loc='bb' where deptno=10;
输出
10 , ACCOUNTING , NEW YORK 10 , aa , bb
before
在sql语句执行后触发after
在sql语句执行后触发create or replace trigger t3 before update on dept for each row begin --打印修改前的数据 dbms_output.put_line(:old.deptno||' , '||:old.dname||' , '||:old.loc); --尝试对:new进行赋值 :new.dname:='a'; :new.loc:='b'; --打印修改后的数据 dbms_output.put_line(:new.deptno||' , '||:new.dname||' , '||:new.loc); end;
修改一条记录
update dept set dname='aa',loc='bb' where deptno=10;
输出
10 , ACCOUNTING , NEW YORK 10 , a , b
发如今上面的例子中
使用before可以修改new的值
使用after时,不能修改new的值
新建日志表
create table dept_log( dt date,--数据的修改时间 opt varchar2(20), --操做(insert,update,delete) old varchar2(100), --修改以前,源数据库的数据 new varchar2(100) --修改以后,数据库中的数据 );
为dept表建立一个触发器,记录dept表的修改日志
create or replace trigger log1 before insert or update or delete on dept for each row declare --声明一个变量保存操做 v_opt varchar2(20); --声明一个变量保存修改前的数据 v_old varchar2(100); --声明一个变量保存修改后的数据 v_new varchar2(100); begin if inserting then v_opt:='insert'; v_old:=null; v_new:=:new.deptno||' , '||:new.dname||' , '||:new.loc; end if; if updating then v_opt:='update'; v_old:=:old.deptno||' , '||:old.dname||' , '||:old.loc; v_new:=:new.deptno||' , '||:new.dname||' , '||:new.loc; end if; if deleting then v_opt:='delete'; v_old:=:old.deptno||' , '||:old.dname||' , '||:old.loc; v_new:=null; end if; insert into dept_log(dt,opt,old,new) values(sysdate,v_opt,v_old,v_new); end;
测试
SQL> insert into dept values(50,'a','b'); 1 row inserted
SQL> update dept set dname='aa',loc='bb' where deptno=50; 1 row updated
SQL> delete from dept where deptno=50; 1 row deleted
查看dept_log表
SQL> select * from dept_log; DT OPT OLD NEW ----------- --------- -------------------- ----------- 2019/12/26 insert 50 , a , b 2019/12/26 update 50 , a , b 50 , aa , bb 2019/12/26 delete 50 , aa , bb
建立一个序列
create sequence seq111 start with 41 increment by 1;
建立一个触发器给dept表自动添加主键
create or replace trigger t4 before insert on dept for each row begin :new.deptno:=seq111.nextval; end;
测试
insert into dept(dname,loc) values('aaa','ccc'); insert into dept(dname,loc) values('aaa','ccc'); insert into dept(dname,loc) values('aaa','ccc'); insert into dept(dname,loc) values('aaa','ccc'); commit;
查看dept表
SQL> select * from dept; DEPTNO DNAME LOC ------ -------------- ------------- 41 aaa ccc 42 aaa ccc 43 aaa ccc 44 aaa ccc 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTON 8 rows selected
注意若是执行插入语句报错,会致使序列空一个数:41,43,44
删除重复数据
delete from dept where deptno between 42 and 44;
若是不少条,重复数据,该如何删除呢
delete from dept t where rowid> (select min(rowid) from dept where dname=t.dname and loc=t.loc);