Oracle 触发器(tigger)

1 触发器类型

触发器在数据库里以独立的对象存储,它与存储过程和函数不同的是,存储过程与函数需要用户显示调用才执行,而触发器是由一个事件来启动运行。即触发器是当某个事件发生时自动地隐式运行。并且,触发器不能接收参数。所以运行触发器就叫触发或点火(firing)。

触发器常用来完成由数据库的完整性约束难以完成的复杂业务规则的约束,或用来监视对数据库的各种操作,实现审计的功能。

1.1 DML触发器

ORACLE可以在DML(insert、update、delete)语句进行,可以在DML操作前或操作后进行触发,并且可以对每个行或语句操作上进行触发。

1.1.1 单列触发:if 列名

create or replace trigger scott.tr_au_student_infoafter update of sno, name on scott.student_infofor each row
beginif :new.sno <> :old.sno or :new.name <> :old.name thenraise_application_error(-20001,'禁止操作!修改 sno = ' || :new.sno || ', name = ' ||:new.name);end if;
end;--测试语句:update scott.student_info tset t.name = '哈哈'where t.sno = 1;--测试结果:弹框 - 错误提醒

1.2 DDL 触发器

触发事件:create、alter、drop

-- **********************************************************************
-- 功能:非 DBA 管理员禁止操作, 如:wangyou
--      限定符合下列 类型 和 域账户 的人,才能操作 create、alter、drop
-- **********************************************************************
create or replace trigger scott.tr_dba_controlbefore create or alter or drop on database
declarev_user_name   varchar2(50); -- 用户名
beginselect sys_context('USERENV', 'OS_USER') into v_user_name from dual;if dbms_standard.dictionary_obj_type in('TABLE', 'SYNONYMS', 'USER', 'TABLESPACE') andv_user_name not in ('wangyou') thenraise_application_error(-20000,v_user_name || '用户无 DDL-' || ora_sysevent ||' 权限,请联系数据架构设计处处理!');end if;
end;

1.3 替代触发器

由于在ORACLE里,不能直接对由两个以上的表建立的视图进行操作。所以给出了替代触发器。它就是ORACLE 8专门为进行视图操作的一种处理方法。

  1. 只适用于视图(多个简单的基表相连),不能直接作用于表上(间接)

  2. 很少使用,不如 dml 触发器来得直观

  3. 必须包含 for each row 选项

create or replace trigger <触发器名称>   instead of insert or update or delete on <视图名>   for each row *-- 必填,且唯一*
begin   pl/sql 语句;
end;

1.4 系统触发器

ORACLE 8i 提供了第三种类型的触发器叫系统触发器。它可以在ORACLE数据库系统的事件中进行触发,如ORACLE系统的启动与关闭等。

触发器组成:

​ 1.触发事件:引起触发器被触发的事件。 例如:DML语句(INSERT, UPDATE, DELETE语句对表或视图执行数据处理操作)、DDL语句(如CREATE、ALTER、DROP语句在数据库中创建、修改、删除模式对象)、数据库系统事件(如系统启动或退出、异常错误)、用户事件(如登录或退出数据库)。

​ 2.触发时间:即该TRIGGER 是在触发事件发生之前(BEFORE)还是之后(AFTER)触发,也就是触发事件和该TRIGGER 的操作顺序。

​ 3.触发操作:即该TRIGGER 被触发之后的目的和意图,正是触发器本身要做的事情。 例如:PL/SQL 块。

​ 4.触发对象:包括表、视图、模式、数据库。只有在这些对象上发生了符合触发条件的触发事件,才会执行触发操作。

​ 5.触发条件:由WHEN子句指定一个逻辑表达式。只有当该表达式的值为TRUE时,遇到触发事件才会自动执行触发器,使其执行触发操作。

​ 6.触发频率:说明触发器内定义的动作被执行的次数。即语句级(STATEMENT)触发器和行级(ROW)触发器。

7.语句级(STATEMENT)触发器:是指当某触发事件发生时,该触发器只执行一次;

8.行级(ROW)触发器:是指当某触发事件发生时,对受到该操作影响的每一行数据,触发器都单独执行一次。

编写触发器时,需要注意以下几点:

​ 1. 触发器不接受参数。

​ 2.一个表上最多可有12个触发器,但同一时间、同一事件、同一类型的触发器只能有一个。并各触发器之间不能有矛盾。

​ 3.在一个表上的触发器越多,对在该表上的DML操作的性能影响就越大。

​ 4.触发器最大为32KB。若确实需要,可以先建立过程,然后在触发器中用CALL语句进行调用。

​ 5. 在触发器的执行部分只能用DML语句(SELECT、INSERT、UPDATE、DELETE),不能使用DDL语句(CREATE、ALTER、DROP)

​ 6.触发器中不能包含事务控制语句(COMMIT,ROLLBACK,SAVEPOINT)。因为触发器是触发语句的一部分,触发语句被提交、回退时,触发器也被提交、回退了。

​ 7.在触发器主体中调用的任何过程、函数,都不能使用事务控制语句。

​ 8.在触发器主体中不能申明任何Long和blob变量。新值new和旧值old也不能是表中的任何long和blob列。

​ 9.不同类型的触发器(如DML触发器、INSTEAD OF触发器、系统触发器)的语法格式和作用有较大区别。

1.5Databse 触发器

触发事件:
startup:'数据库打开'时,相反的 = shutdown
logon  :当用户连接到数据库并 '建立会话' 时,相反的 = logoff
servererror:发生服务器错误时
--建表
create table scott.database_login_info (client_ip      varchar2(30),login_user     varchar2(30),database_name  varchar2(30),database_event varchar2(30),create_user    varchar2(50),create_data    date
);--触发器
create or replace trigger scott.tr_al_database_login_infoafter logon on database
declarev_option_user varchar2(50) := sys_context('USERENV', 'OS_USER'); -- 电脑域账户
begininsert into scott.database_login_info(client_ip,login_user,database_name,database_event,create_user,create_data)values(dbms_standard.client_ip_address,dbms_standard.login_user,dbms_standard.database_name,dbms_standard.sysevent,v_option_user,sysdate);
end;

s

2. 创建触发器

create [or replace] trigger 触发器名触发时间 {before | after}           -- view 中是 instead of触发事件 {insert | update | delete} -- dml、ddl、database
on 触发对象                            -- table、view、schema、database 触发频率 {for each row}            -- 行级触发器。默认:语句级触发器[follows 其它触发器名]              -- 多个触发器执行的 前后顺序[when 触发条件]
beginpl/sql 语句;
end;

关键字说明:

  1. 触发器名:一般格式 tr_*

  2. 触发时间:在 ‘触发事件’ 发生之前(before)还是之后(after)

  3. 触发事件:根据不同的 ‘触发事件’,可以分为不同的 ‘类型’

  4. 触发对象:table、view、schema、database

  5. 触发频率:‘语句级触发器’(默认)指触发一次,‘行级触发器’ 每一行触发一次

  6. 触发条件:仅当 ‘触发条件’ 为 True 时,才执行 pl/sql 语句

    基础数据准备:

    create table scott.student_info (sno   number(10),name  varchar2(30),sex   varchar2(2)
    );
    insert into scott.student_info(sno, name, sex) values(1, '张三', '女');
    insert into scott.student_info(sno, name, sex) values(2, '李四', '男');
    insert into scott.student_info(sno, name, sex) values(3, '王五', '女');
    commit;
    

2.1for each row

/*
功能:after insert or update or delete 时,执行语句
命名:tr_aiud_student_info
*/
create or replace trigger scott.tr_aiud_student_infoafter insert or update or delete on scott.student_infofor each row
begincasewhen inserting thendbms_output.put_line('插入成功!');when updating thendbms_output.put_line('更新成功!');when deleting thendbms_output.put_line('删除成功!');elsedbms_output.put_line('无操作!');end case;
end;
/

测试语句:

update scott.student_info tset t.sex = '1'where t.sno <= 3;

PL/SQL 输出窗口:3 条记录,故共触发 3 次

更新成功!
更新成功!
更新成功!

提示:若去掉 for each row,再执行上述操作,则仅触发 1

2.2 follows

前提:触发器的执行是否需要指定 '先后顺序'?
1. 若不需要,则无需 follows 关键字
2. 若需要   (1) before 和 after 能否区分,若能,则无需 follows 关键字   (2) 最后,才用 follows 区分
/*触发器1:*/create or replace trigger scott.tr_ai_student_info_1after insert on scott.student_infofor each row
beginif inserting thendbms_output.put_line('插入操作 1');end if;
end;
//*触发器2:(顺序:先触发器1,再触发器2)*/create or replace trigger scott.tr_ai_student_info_2after insert on scott.student_infofor each ROWFOLLOWS scott.tr_ai_student_info_1
beginif inserting thendbms_output.put_line('插入操作 2');end if;
end;
//*测试语句:*/insert into scott.student_info(sno, name, sex) values(5, '赵六', '女');/*PL/SQL 输出窗口:*/
插入操作 1
插入操作 2

2.3 when

1. when:增加触发条件
2. when 中的 new、old 是不带 : 的    (不是 :new、:old)
create or replace trigger scott.tr_ad_student_infoafter delete on scott.student_infofor each rowwhen (old.sno = 1)   -- sno = 1 的记录禁止被删除!
beginif deleting thenraise_application_error(-20001, '此条记录禁止删除,sno = ' || :old.sno);end if;
end;
//*测试语句:*/
delete from scott.student_info t where t.sno = 1;/*测试结果*/
弹框 - 错误提醒

2.3.查询触发器

--权限范围,由大到小:dba_* > all_* > user_*
select * from dba_triggers;
select * from all_triggers;
select * from user_triggers;

2.5.删除触发器

drop trigger 触发器名;
select 'DROP TRIGGER ' || t.owner || '.' || t.trigger_name || ';' 删除from all_triggers twhere t.owner = 'SCOTT'and t.table_name = 'STUDENT_INFO';

2.6.常用属性

2.6.1 inserting、updating、deleting

1. 前提条件:无
2. 表示含义inserting = insert 操作updating  = update 操作deleting  = delete 操作

2.4.2 now、old

1. 前提条件:for each row
2. 表示含义:new = 触发前的值:old = 触发后的值
3. 说明 (1) new、old 均为 '默认值', 常用, 一般无需更改referencing new as new old as old       (2) 若想要更改,如:new => new_new,old => old_old  referencing new as new_new old as old_old

:new、:old 值分布情况:

insert update delete
:new ×
:old ×
create or replace trigger scott.tr_au_student_infoafter update on scott.student_infofor each row
begin-- 旧值dbms_output.put_line('old.sno = ' || :old.sno);dbms_output.put_line('old.name = ' || :old.name);dbms_output.put_line('old.sex = ' || :old.sex);dbms_output.put_line('------');-- 新值dbms_output.put_line('new.sno = ' || :new.sno);dbms_output.put_line('new.name = ' || :new.name);dbms_output.put_line('new.sex = ' || :new.sex);
end;
/--测试语句:
update scott.student_info tset t.name = 'name',t.sex = '2'where t.sno = 1;--测试结果:PL/SQL 输出窗口
old.sno = 1
old.name = 张三
old.sex = 女
------
new.sno = 1
new.name = name
new.sex = 2

当一个基表被修改( INSERT, UPDATE, DELETE)时要执行的存储过程,执行时根据其所依附的基表改动而自动触发,因此与应用程序无关,用数据库触发器可以保证数据的一致性和完整性。

BEFORE INSERTBEFORE INSERT FOR EACH ROWAFTER INSERTAFTER INSERT FOR EACH ROWBEFORE UPDATEBEFORE UPDATE FOR EACH ROWAFTER UPDATEAFTER UPDATE FOR EACH ROWBEFORE DELETEBEFORE DELETE FOR EACH ROWAFTER DELETEAFTER DELETE FOR EACH ROW

总结

3.1 触发器触发次序

  1. 执行 BEFORE语句级触发器;

  2. 对与受语句影响的每一行:

​ 执行 BEFORE行级触发器

​ 执行 DML语句

​ 执行 AFTER行级触发器

  1. 执行 AFTER语句级触发器

3.2 创建DML触发器

触发器名与过程名和包的名字不一样,它是单独的名字空间,因而触发器名可以和表或过程有相同的名字,但在一个模式中触发器名不能相同。

DML触发器的限制

​ CREATE TRIGGER语句文本的字符长度不能超过32KB;

​ 触发器体内的SELECT 语句只能为SELECT … INTO …结构,或者为定义游标所使用的SELECT 语句。

​ 触发器中不能使用数据库事务控制语句 COMMIT; ROLLBACK, SVAEPOINT 语句;

​ 由触发器所调用的过程或函数也不能使用数据库事务控制语句;

​ 触发器中不能使用LONG, LONG RAW 类型;

​ 触发器内可以参照LOB 类型列的列值,但不能通过 :NEW 修改LOB列中的数据;

DML触发器基本要点

​ **触发时机:**指定触发器的触发时间。如果指定为BEFORE,则表示在执行DML操作之前触发,以便防止某些错误操作发生或实现某些业务规则;如果指定为AFTER,则表示在执行DML操作之后触发,以便记录该操作或做某些事后处理。

​ **触发事件:**引起触发器被触发的事件,即DML操作(INSERT、UPDATE、DELETE)。既可以是单个触发事件,也可以是多个触发事件的组合(只能使用OR逻辑组合,不能使用AND逻辑组合)。

​ **条件谓词:**当在触发器中包含多个触发事件(INSERT、UPDATE、DELETE)的组合时,为了分别针对不同的事件进行不同的处理,需要使用ORACLE提供的如下条件谓词。

INSERTING : 当触发事件是INSERT时,取值为TRUE,否则为FALSE。

**UPDATING : [(column_1,column_2,…,column_x)]:**当触发事件是UPDATE 时,如果修改了column_x列,则取值为TRUE,否则为FALSE。其中column_x是可选的。

DELETING : 当触发事件是DELETE时,则取值为TRUE,否则为FALSE。

​ **解发对象:**指定触发器是创建在哪个表、视图上。

​ **触发类型:**是语句级还是行级触发器。

​ **触发条件:**由WHEN子句指定一个逻辑表达式,只允许在行级触发器上指定触发条件,指定UPDATING后面的列的列表。

问题:当触发器被触发时,要使用被插入、更新或删除的记录中的列值,有时要使用操作前、 后列的值.

实现: :NEW 修饰符访问操作完成后列的值

​ :OLD 修饰符访问操作完成前列的值

特性 INSERT UPDATE DELETE
OLD NULL 实际值 实际值
NEW 实际值 实际值 NULL

例1: 建立一个触发器, 当职工表 emp 表被删除一条记录时,把被删除记录写到职工表删除日志表中去。

CREATE TABLE emp_his AS SELECT * FROM EMP WHERE **1**=**2**;CREATE OR REPLACE TRIGGER tr_del_emp   BEFORE DELETE --指定触发时机为删除操作前触发  ON scott.emp   FOR EACH ROW  --说明创建的是行级触发器BEGIN  --将修改前数据插入到日志记录表 del_emp ,以供监督使用。  INSERT INTO emp_his(deptno , empno, ename , job ,mgr , sal , comm , hiredate )    VALUES( :old.deptno, :old.empno, :old.ename , :old.job,:old.mgr, :old.sal, :old.comm, :old.hiredate );END;DELETE emp WHERE empno=**7788**;DROP TABLE emp_his;DROP TRIGGER del_emp;

**例2:**限制对Departments表修改(包括INSERT,DELETE,UPDATE)的时间范围,即不允许在非工作时间修改departments表。

CREATE OR REPLACE TRIGGER tr_dept_timeBEFORE INSERT OR DELETE OR UPDATE ON departmentsBEGIN IF (TO_CHAR(sysdate,'DAY') IN ('星期六', '星期日'))OR (TO_CHAR(sysdate, 'HH24:MI') NOT BETWEEN '08:30' AND '18:00')THEN   RAISE_APPLICATION_ERROR(-**20001**, '不是上班时间,不能修改departments表');END IF;END;

Oracle 触发器(tigger)4相关推荐

  1. [转载]Oracle触发器用法实例详解

    本文实例讲述了Oracle触发器用法.分享给大家供大家参考,具体如下: 一.触发器简介 触发器的定义就是说某个条件成立的时候,触发器里面所定义的语句就会被自动的执行. 因此触发器不需要人为的去调用,也 ...

  2. oracle中触发器的语法,Oracle 触发器语法及实例

    Oracle 触发器语法及实例 Oracle触发器语法(一) 一Oracle触发器语法 触发器是特定事件出现的时候,自动执行的代码块.类似于存储过程,触发器与存储过程的区别在于:存储过程是由用户或应用 ...

  3. oracle中触发器的创建,Oracle触发器创建及其功能

    Oracle触发器创建及其功能 下面的文章主要介绍的是如何创建Oracle触发器,同时介绍了Oracle触发器的功能.语法,而且通过具体的例子可以让大家更深入的`掌握. 1.创建表t1 :create ...

  4. Oracle 触发器调用存储过程|转||待研究|

    Oracle触发器调用存储过程资料收集整理 触发器:Trigger 存储过程:Stored Procedure // ******************** 收集1 **************** ...

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

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

  6. oracle触发器高级教程

    [转自]http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_7004.htm#i2153503 CREA ...

  7. oracle行级的触发器,Oracle触发器Trigger2行级

    create table trigger_t2( id int, name varchar(30), age int ); /* --创建一个before update的触发器-控制每一行,行级 -- ...

  8. oracle触发器 select into,Oracle触发器中selectinto报错no_data_found异常处理

    Oracle触发器中select into 报错no_data_found异常处理 红色部分为对查询不到数据异常的处理 create or replace trigger TIG_MONITOR_AL ...

  9. oracle中触发器的语法,解析Oracle触发器的语法

    导读:触发器是一种特殊的存储过程,触发器的执行不是由程序调用,也不是手工启动,而是由事件来触发,Oracle数据库是大家非常熟悉的数据库系统啦,那么Oracle触发器的语法是怎样的呢?下文中将为大家带 ...

最新文章

  1. 一个有趣的实验:用0.1f 替换 0,性能提升 7 倍!
  2. iovec结构体定义及使用
  3. windows密钥连接linux,windows使用密钥登录linux
  4. Nginx, HTTPS的配置
  5. C++的const比C语言#define更好的原因?
  6. 信息学奥赛一本通 2047:【例5.16】过滤空格 | OpenJudge NOI 1.7 23:过滤多余的空格
  7. CSS3 Media Query 响应式媒体查询
  8. es6 新增数据类型_ES6新增特性整理
  9. python序列中各元素之间存在顺序关系_《Python Cookbook(第3版)中文版》——1.10 从序列中移除重复项且保持元素间顺序不变-阿里云开发者社区...
  10. from django.core.context_processors import crsf报错
  11. poj 1958 Strange Towers of Hanoi dp,需要仔细读题
  12. 29.优化 MySQL Server
  13. convertTO函数 简介
  14. Jpa是什么——Jpa使用详解
  15. HAL学习笔记-3 HAL库介绍
  16. 3t硬盘哪个服务器系统识别,3T硬盘为何不能被系统完全识别
  17. 抖音上爆红的美女动态代码图如何实现?
  18. 二十一世纪大学英语读写基础教程学习笔记(原文)——10 - The Future(未来)
  19. 感人:留给老婆下任老公的信
  20. 双向 DC-DC 变换器(A 题 本科组)-- 2015 年全国大学生电子设计竞赛试题

热门文章

  1. ubuntu卸载福昕阅读器
  2. 计算机三级数据库技术——第一章 数据库应用系统开发方法学习笔记
  3. ffmpeg vsync参数分析
  4. 【RHCE】NFS服务器简介及简单共享目录配置
  5. 「 C++ 函数 」“WSAStartup()使用”讲解
  6. C# ComboBox 下拉选项框
  7. ubuntu 安装mysql 源码,命令ubuntu上用源代码安装mysql的详细操作说明
  8. Linux主机下连接远程postgresql数据库、容器版postgresql数据库
  9. staruml 免费版
  10. 海思系统开发——linux下挂载SD卡