触发器:在执行insert,updatedalete语句时,
触发执行的一段plsql代码
可以在sql语句执行前触发,也可以在sql语句执行后触发,
还可以替换原sql语句只执行触发器代码
让触发器失效
alter trigger 触发器名 disable;
让触发器生效
alter trigger 触发器名 enable;
删除触发器
drop trigger 触发器名;
表级触发器:一个sql语句只会触发一次触发器代码
语法
create trigger 触发器名称
before|alter insert[or delete[or update]] on 表名
begin
end;
给emp创建一个触发器,当给emp表插入数据时,打印‘插入数据‘
新建t1触发器
create trigger t1
before insert on emp
begin
dbms_output.put_line('插入数据');
end;
插入数据进行测试
insert into emp(empno,ename,deptno) values(7123,'asd',10);
rollback;
会输出
插入数据
尝试插入多条数据
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);
原文:https://www.cnblogs.com/inmeditation/p/12104798.html