Oracle触发器简单使用记录
在ORACLE系统里,触发器类似函数和过程。
1、触发器类型:(一般为:语句级触发器和行级触发器。)
1)、DML触发器: 创建在表上,由DML事件引发
2)、instead of触发器: 创建在视图上并且只能在行级上触发,用于替代insert,delete等操作(由于oracle中不能直接对有两个以上的表建立的视图进行DML操作,所以给出替代触发器,它是专门为进行视图操作的一种处理方法)
3)、DDL触发器: 触发事件时数据库对象的创建和修改
4)、数据库事件触发器:定义在数据库或者模式上,由数据库事件触发
语法:
create or replace trigger 触发器名
<before | after | instead of> <insert | update | delete>--<insert | update | delete>可以选择一个或多个DML语句,如果选择多个,则用or分开,如:insert or update。
on 表名或者视图名或者用户名或者数据库名
[for each row] [触发级别]针对一个表或视图创建trigger时分为statement级别与row级别的trigger.所谓statement级别是说一个sql语句触发一次trigger,而如果是row级别则一个sql语句涉及到多行数据则trigger会被触发多次
when(condition)[when判断条件]
[declare 变量] 11g
begin
pl/sql语句;
end 触发器名;
(注:代码涉及到对关联表的数据操作,在行级触发器中使用,将会报ORA-04091错误。这时可以通过自制事务来规避,弊端是使用自制事务后无法回滚rollback)
触发时间:before/after 在指定的事件发生之前/后执行触发器 instead of 触发器用在对视图的更新上。
触发事件:Insert,update,delete,create(创建对象时),alter,drop,logon/logoff(用户的登录或注销时执行触发器),startup/shutdown(数据库打开或关闭时执行触发器)。
常见的是DML(insert,update,delete) , DDL(create,alter,drop)语句
触发级别:for each row(行级触发)对触发事件影响的每一行执行触发器,即触发机制是基于行的。改一行数据,触发一次。
不写为语句触发(对触发事件只能触发一次,而且不能该问受触发器影响的每一行的值。既无论这条SQL语句影响多少条记录,触发器都只触发一次。)
WHEN后跟的condition:是触发器的响应条件,只对BEFORE和AFTER行级触发器有效,当操作的记录满足condition时,触发器才被执行,否则不执行。Condition中可以通过new对象和old对象不带“:”(注意区别于前面的:new和:old,在代码中引用需要加上冒号)来引用操作的记录。
2、简例
创建测试用表:
create table emp_bak1 as select * from emp;
create table emp_bak2 as select * from emp;
例1:
create or replace trigger insert_emp
after insert on emp_bak1
for each row
declare --Declare后面跟的是本地变量定义部分,如果没有本地变量定义,此部分可以去掉
test_val emp_bak1.ename%type;--根据表的字段定义变量类型
begin
dbms_output.put_line('员工编号:'||:new.empno);
dbms_output.put_line('员工姓名:'||:new.ename);
dbms_output.put_line('职位:'||:new.job);
dbms_output.put_line('工资:'||:new.sal);
dbms_output.put_line('所在部门:'||:new.deptno);
dbms_output.put_line('---触发器已被执行---');
--select ename into test_val from emp_bak1 where empno = 7839;--ORA-04091
select :new.empno into test_val from dual;
dbms_output.put_line('---测试--->'||test_val);
end; insert into emp_bak1 (empno, ename, job, sal, deptno) values ('', 'SM', 'IT', '', '');
oracle默认的 用old代表老数据 new代表新数据(这两个变量只有在使用了关键字 "FOR EACH ROW"时才存在;referencing new as new_val old as old_val:这个可以更改新旧值的名字来引用新值,旧值)
insert时 只有new 没有old
delete时 只有old 没有new
update时 二者都可用
create or replace trigger delete_emp
before delete on emp_bak1 --删除操作前触发
for each row
begin
insert into emp_bak2
(empno, ename, job, sal, deptno)
values
(:old.empno, :old.ename, :old.job, :old.sal, :old.deptno);
dbms_output.put_line('-----有数据删除,员工号为'||:old.empno||'详细信息见emp_bak2表------');
end delete_emp; insert into emp_bak1 (empno, ename, job, sal, deptno) values ('', 'K', 'TE', '', '');
delete from emp_bak1 where empno = 777;
例2:指定条件列触发
create or replace trigger tri_01
after insert or update of sal on emp_bak1
for each row
begin
if inserting then
dbms_output.put_line('新人入驻有收入sal');
elsif updating then
dbms_output.put_line('sal有变动');
end if;
end tri_01; update emp_bak1 set sal = 888 where empno = 7934;--触发
update emp_bak1 set comm = 666 where empno = 7934;--未触发
注:第二行中的of sal on emp_bak1 是在表emp_bak1的sal字段发生变更时才触发操作,
在触发器主体的if语句表达式中,inserting, updating和deleting可以用来区分当前是在做哪一种DML操作,可以作为把多个类似触发器合并在一个触发器中判别触发事件的属性。
例3:when条件限制
create or replace trigger tri_02
before update of sal, comm or delete on emp_bak1
for each row
when (old.deptno = 30) --注:old前不带':'且结尾不带';'
begin
case
when updating('sal') then
dbms_output.put_line('原来薪资:'||:old.sal||';变更后薪资:'||:new.sal||';');
if :new.sal < :old.sal then
dbms_output.put_line('降薪不被允许');
raise_application_error(-20001, '部门30的人员的工资不能降');
end if;
when updating('comm') then
dbms_output.put_line('原来奖金:'||:old.comm||';变更后奖金:'||:new.comm||';');
if :new.comm < :old.comm then
dbms_output.put_line('降奖金不被允许');
raise_application_error(-20002, '部门30的人员的奖金不能降');
end if;
when deleting then
raise_application_error(-20003, '部门30的人员不能删');
end case;
end;
select * from emp_bak1 where deptno = 30;
update emp_bak1 set comm = 2000 where empno = 7499;
update emp_bak1 set sal = 20000 where empno = 7698;
raise_application_error相当于拒绝了插入或者修改事务
oracle允许自定义的错误代码的范围为-20000-->20999
raise_application_error(-20001,'ErrorCode');
例4:instead of触发器
instead of 选项使ORACLE激活触发器,而不执行触发事件。只能对视图和对象视图建立instead of触发器,而不能对表、模式和数据库建立instead of 触发器。
--语法类似:
create [or replace] trigger trigger_name
instead of
{insert | delete | update [of column [, column …]]}
on view_name --只能定义在视图上
[referencing {old [as] old_val | new [as] new_val| parent as parent}]--可以给old/new对象赋予新的名称(可以不要)
[for each row ] --因为instead of触发器只能在行级上触发,所以没有必要指定
[when condition]
pl/sql_block | call procedure_name;
视图创建
create view view_emp as
select deptno,count(*) count_no,sum(sal) sal from emp group by deptno;
对基表处理过的视图,在删除时会报下面的错误
ORA-01732: 此视图的数据操纵操作非法
此时可以创建INSTEAD_OF触发器来为 DELETE 操作执行所需的处理,即删除EMP表中所有基准行
create or replace trigger view_tri_03
instead of delete on view_emp
for each row
begin
delete from emp where deptno= :old.deptno;
dbms_output.put_line('从emp基表中删除部门编号为:'||:old.deptno||'的基础人员数据。');
end view_tri_03;
可看出此触发器只是触发了一个删除部门号的事件,实际更改的还是基表。
例5:语句级触发器
create or replace trigger tri_04
after insert or update of sal on emp_bak1
declare
v_sumsal number;
begin
select sum(sal) into v_sumsal from emp_bak1;
if v_sumsal > 50000 then
raise_application_error(-20001, '总工资超过50000');
end if;
end;
--如果用行级触发器(for each row)会报ORA-04091错误
insert into emp_bak1 (empno, ename, job, sal, deptno) values ('777', 'K', 'TE', '90000', '30');
(注:此为学习记录笔记,仅供参考若有问题请指正,后续补充......)
参考资料:https://www.cnblogs.com/wishyouhappy/p/3665851.html
参考资料:https://blog.csdn.net/weiwenhp/article/details/9179891
参考资料:https://www.cnblogs.com/hyq0002013/p/6085981.html
参考资料:https://blog.csdn.net/IndexMan/article/details/8023740
Oracle触发器简单使用记录的更多相关文章
- Oracle触发器简单入门记录
写在前面: 最近,老项目新增了日报优化的需求,丽姐让我用触发器去实现当数据插入或者更新的时候,实现对日报表数据更新操作.嗯嗯嗯呢,之前学习数据库的时候,有碰到过触发器,但都是一跳而过,也没怎么去真正的 ...
- 【oracle】触发器简单实现
目标:实现实时备份uertest表数据至usertest_temp中,两表结构一致 解决:用oracle触发器实现同步 结果: 1.建表 -- 简单的用户表 create table USERTEST ...
- (转)oracle触发器使用:after insert 与before insert的简单使用注意
本文转载自:http://blog.csdn.net/kuangfengbuyi/article/details/41446125 创建触发器时,触发器类型为after insert , 在begin ...
- oracle触发器加条件判断
oracle触发器加条件判断,如果某个字段,isnode=0,那么不执行下面的方法,数据如下: create or replace trigger tr_basestation_insert_emp ...
- Oracle 触发器在日志管理开发中的应用
摘要: 本文讨论了利用数据库中的触发器对日志管理进行设计与实现的方法, 是对原来在客户端软件中编写日志管理方法的一种改进, 并给出了 Oracle9i 中的实例演示.关键词: Oracle; 触发器; ...
- SQL server与Oracle触发器的创建与使用
SQL Server 1创建触发器 GO BEGIN IF (object_id('WMY', 'tr') is not null) DROP trigger WMY END; GO CREATE T ...
- Oracle触发器用法实例详解
转自:https://www.jb51.net/article/80804.htm. 本文实例讲述了Oracle触发器用法.分享给大家供大家参考,具体如下: 一.触发器简介 触发器的定义就是说某个条件 ...
- Oracle复习(有记录才能沉淀.......)
一.Oracle准备工作 1.安装Oracle Oracle数据库产品是免费的,我们可以从Oracle的官方网站(http://www.oracle.com)下载到程序安装包,Oracle在Windo ...
- 问题:Oracle出发器;结果:1、Oracle触发器详解,2、Oracle触发器示例
ORACLE触发器详解 本篇主要内容如下: 8.1 触发器类型 8.1.1 DML触发器 8.1.2 替代触发器 8.1.3 系统触发器 8.2 创建触发器 8.2.1 触发器触发次序 8.2.2 创 ...
随机推荐
- "软掩膜"和“硬掩膜”-智能IC卡
目录 一.“软掩膜”和“硬掩膜”... 2 二.EMV迁移进程... 3 三.PBOC规范和EMV规范对比... 3 四.总结... 5 五.关于SDA和DDA. 6 一.“软掩膜”和“硬掩膜” “软 ...
- 基于保守性和规则性的预测方法SIFT和PolyPhen
有什么特征可以帮助我们来区分导致功能和表型变化的变异和其他变异,然后我们如何综合特征来做出一个预测模型? 表型或功能的改变(phenotypical/functional effect)a,个体表型上 ...
- springmvc框架简单搭建
一.利用xml 配置 1.web.xml <web-app version="2.4" xmlns="http://java.sun.com/xml/n ...
- javascript总结38: 神奇的this
1 this的特性 this 是在函数中的 this 的指向 是在函数调用的时候决定的 this的指向. 谁调用这个函数,函数中的this就指向谁 function fn (){ console.lo ...
- CodeForces 540D Bad Luck Island (DP)
题意:一个岛上有石头,剪刀和布,规则就不用说了,问你最后只剩下每一种的概率是多少. 析:很明显的一个概率DP,用d[i][j][k]表示,石头剩下 i 个,剪刀剩下 j 个,布剩下 k 个,d[r][ ...
- 从零开始学习前端JAVASCRIPT — 9、JavaScript基础RegExp(正则表达式)
1:正则的概念 正则表达式(regular expression)是一个描述字符规则的对象.可以用来检查一个字符串是否含有某个子字符串,将匹配的子字符串做替换或者从某个字符串中取出符合某个条件的子串等 ...
- c#范型
泛型介绍:范型类和范型方法同事具备可重用性.类型安全和效率,这是非范型类和非范型方法无法具备的. 所谓范型,即通过参数化类型实现同一份代码上操作多种数据类型,范型编程是一种编程范式,它利用“参数化类型 ...
- 【Linux】Vim编辑器
本文基于Debian 1.vim使用简介 1.1vim安装 使用apt安装vim即可: sudo apt-get install vim 1.2 vim编辑器的模式 vim编辑器分为命令模式和编辑模式 ...
- imagelist用法
1.添加一个Imagelist控件,并双击控件图标如下图 2.点击新增按钮
- Java Integer为代表的包装类
Java种的Integer是int的包装类型 1. Integer 是int的包装类型,数据类型是类,初值为null 2. 初始化时 int i = 1; Integer i = new Intege ...