在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触发器简单使用记录的更多相关文章

  1. Oracle触发器简单入门记录

    写在前面: 最近,老项目新增了日报优化的需求,丽姐让我用触发器去实现当数据插入或者更新的时候,实现对日报表数据更新操作.嗯嗯嗯呢,之前学习数据库的时候,有碰到过触发器,但都是一跳而过,也没怎么去真正的 ...

  2. 【oracle】触发器简单实现

    目标:实现实时备份uertest表数据至usertest_temp中,两表结构一致 解决:用oracle触发器实现同步 结果: 1.建表 -- 简单的用户表 create table USERTEST ...

  3. (转)oracle触发器使用:after insert 与before insert的简单使用注意

    本文转载自:http://blog.csdn.net/kuangfengbuyi/article/details/41446125 创建触发器时,触发器类型为after insert , 在begin ...

  4. oracle触发器加条件判断

    oracle触发器加条件判断,如果某个字段,isnode=0,那么不执行下面的方法,数据如下: create or replace trigger tr_basestation_insert_emp ...

  5. Oracle 触发器在日志管理开发中的应用

    摘要: 本文讨论了利用数据库中的触发器对日志管理进行设计与实现的方法, 是对原来在客户端软件中编写日志管理方法的一种改进, 并给出了 Oracle9i 中的实例演示.关键词: Oracle; 触发器; ...

  6. SQL server与Oracle触发器的创建与使用

    SQL Server 1创建触发器 GO BEGIN IF (object_id('WMY', 'tr') is not null) DROP trigger WMY END; GO CREATE T ...

  7. Oracle触发器用法实例详解

    转自:https://www.jb51.net/article/80804.htm. 本文实例讲述了Oracle触发器用法.分享给大家供大家参考,具体如下: 一.触发器简介 触发器的定义就是说某个条件 ...

  8. Oracle复习(有记录才能沉淀.......)

    一.Oracle准备工作 1.安装Oracle Oracle数据库产品是免费的,我们可以从Oracle的官方网站(http://www.oracle.com)下载到程序安装包,Oracle在Windo ...

  9. 问题: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 创 ...

随机推荐

  1. Java中的Set,List,Map的区别

    1. 对JAVA的集合的理解是想对于数组 数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型/引用类型) JAVA集合可以存储和操作数目不固定的一组数据. 所有的JAVA集合都位于 ja ...

  2. CircRNA 环化RNA

    2016国自然新秀CircRNA的研究策略和分析  

  3. C# 银行系统

    今天分享一个大家都爱的Money 银行系统代码  可以随心所欲的存钱取钱 //要想成功,必须马到 //建立数组 Card[] cards = ]; //卡类初始化 public void Initia ...

  4. css基础 引用方式 标签选择器 优先级 各式布局

    今天讲的css基础,了解了css即层叠式表,是美化网页,控制页面的样式. 样式表引进网页的3种方式1内联式,语法例子:<div style="width: 100px;height: ...

  5. CodeForces 907F Power Tower(扩展欧拉定理)

    Priests of the Quetzalcoatl cult want to build a tower to represent a power of their god. Tower is u ...

  6. Java文件路径

    几大常用的方法 Class.getResource("")    返回的是当前Class这个类所在包开始的位置 getClassLoader().getResource(" ...

  7. python二维码操作:QRCode和MyQR入门

    1.QRCode QRCode最简单的使用 import qrcode qrcode.make("第一个二维码").get_image().show() 根据文本生成二维码并且直接 ...

  8. [LeetCode 题解]: Roman to Interger

    前言   [LeetCode 题解]系列传送门:  http://www.cnblogs.com/double-win/category/573499.html   1.题目描述 Given a ro ...

  9. Nginx源码编译

    1. 概述 有时由于添加了自己编写的c++模块,或者改了源码的一些名称.配置什么的,需要自行编译nginx. 可以先下下来源码,然后需要的话就自己改下源码或增加模块,最后再编译成linux或者wind ...

  10. 1. Python2 ,Python3区别

    Python2: 1. 源码都含有PHP,Java,C等语言的规范陋习. 2.重复代码比较多. Python3: 源码很规范,清晰,简单,符合Python的宗旨.