一、触发器

  触发器是当特定事件出现时自动执行的代码块。比如,每次对员工表进行增删改的操作时,向日志表中添加一条记录。触发器和存储过程是由区别的:触发器是根据某些条件自动执行的,存储过程是手动条用的。

  (一)触发器的类型:

    1、行级触发器:操作数据行的时候触发。

    2、语句级触发器:一个DML语句出发一次的触发器。行级触发器和语句级触发器一起也成为DML触发器。

    3、INSTEADOF 触发器:主要是在视图上定义的触发器。

    4、模式触发器:用户事务触发器。

    5、数据库触发器:创建在数据库事件上的触发器。

  (二)触发器可以分为三个部分:

    1、触发器语句:触发器语句是哪些可以导致触发器的事件,即在表或者视图上执行INSERT、DELETE、UPDATE之类的DML语句,在模式对象上执行的DDL语句或数据库事件。所有可以导致触发器的事件都是触发器的语句。

    2、触发器限制:触发器限制条件包含一个布尔表达式,该值必须为”真“才能激活触发器,如果该值为”假“或”未知“,将不运行触发器操作。

    3、触发器操作:触发器操作时触发器的主体,包含一些SQL语句和代码,这些代码在执行触发器有且触发器限制条件为”真“时运行。行级触发器允许触发器操作中的语句访问行的列值。

  

  (三)触发器的常用功能如下:

  1、允许/限制对表的修改。

  2、自动生成派生列。

  3、强制数据一致性。

  4、强制复杂的完整性约束条件。

  5、提供审计和日志记录。

  6、防止无效的事件处理。

  7、启动复杂的业务逻辑。

  由于触发器是对数据进行监控的一个对象,随时监控着数据库中的数据和表,造成使用触发器的性能低下。这点尤为重要。

二、创建触发器:

  语法:

  CREATE [OR REPLACE] TRIGGER trigger_name

  {BEFORE | AFTER | INSTEAD OF}

  {INSERT | DELETE | UDPATE | [OF column[,column]]}

  [OR {INSERT | DELETE | UPDATE [OF column[,column]]}]

  ON [schema.]table_or_view_name

  [REFERENCING [NEW AS new_row_name] [OLD AS old_row_name]]

  [FOR EACH ROW]

  [WHEN (condition)]

  [DECLARE

    variable_declation]

  BEGIN

    statements;

  [EXCEPTION

    exception_handlers]

  END[trigger_name];

  说明:

  trigger_name:触发器的名称

  BEFORE | AFTER :表示在事件发生之前或之后激活触发器

   INSTEAD OF:表示可以执行触发器代码来代替导致触发器调用的事件。

  INSERT | DELETE | UDPATE :指定构成触发器事件的数据库操作类型,UPDATE还可以指定列的列表。

  REFERENCING :指定新行(即将更新)和旧行(更新前)的其他名称,默认为NEW和OLD。

  table_or_view_name:触发器所监控的表或者视图的名称。

  FOR EACH ROW:表示是否对受影响的每一行都执行触发器,即行级触发器。如果不使用此语句,则为语句触发器,使用此语句则为行级触发器。

  WHEN (condition):限制执行触发器的条件,该条件可以包括新旧数据值的检查。

  DECLARE:声明触发器所使用的局部变量

  statements:触发器所执行的PL-SQL语句。

  exception_handlers:异常处理代码。

  例1:生成一个自动编号(行级触发器)

--创建测试表,学生表
CREATE TABLE student
(
stu_id NUMBER CONSTRAINT pk_id PRIMARY KEY,
stu_name VARCHAR2(20) NOT NULL,
stu_phone VARCHAR2(20) NOT NULL
);
--创建一个序列,从1开始累加,每次加1
CREATE SEQUENCE seq_student
START WITH 1 --序列开始,从1开始计数
INCREMENT BY 1 --每次增加1
NOMAXVALUE --不设置最大值
NOCYCLE --只累加,不循环
CACHE 20; --缓存20
create or replace trigger student_insert_seq
before insert on student --在插入之前
for each row --行级触发器
begin
:new.stu_id := seq_student.nextval; --将插入的stu_id属性设置为序列的下一个值
end student_insert_seq;
--插入数据
INSERT INTO student (stu_name,stu_phone) VALUES('张三','');
INSERT INTO student (stu_name,stu_phone) VALUES('李四',''); --查询,数据插入成功
SELECT * FROM student

  例2:实现表操作日志  

--新建日志表序列
CREATE SEQUENCE logs_id_squ INCREMENT BY 1
START WITH 1 MAXVALUE 9999999 NOCYCLE NOCACHE; --日志表
CREATE TABLE logs(
LOG_ID NUMBER(10) PRIMARY KEY,
LOG_TABLE VARCHAR2(10) NOT NULL,
LOG_DML VARCHAR2(10),
LOG_KEY_ID NUMBER(10),
LOG_DATE DATE,
LOG_USER VARCHAR2(15)
);
--创建日志触发器:表级触发器
create or replace trigger trig_log
after INSERT OR UPDATE OR DELETE
on emp
for each row
DECLARE
V_USERNAME VARCHAR2(20);
BEGIN
SELECT USER INTO V_USERNAME FROM dual; --获取当前用户
IF INSERTING THEN
INSERT INTO logs VALUES(logs_id_squ.nextval,'emp','insert',:new.Empno,sysdate,V_USERNAME);
ELSIF UPDATING THEN
INSERT INTO logs VALUES(logs_id_squ.nextval,'emp','update',:new.Empno,sysdate,V_USERNAME);
ELSIF DELETING THEN
INSERT INTO logs VALUES(logs_id_squ.nextval,'emp','delete',:new.Empno,sysdate,V_USERNAME);
END IF;
END TRIG_LOG;

三、触发器的注意事项

(1)、create trigger 语句的字符长度不能超多32kb;

(2)、触发器体内的select语句只能为select .....into .....结构,或者为定义游标所使用的select语句;

(3)、触发器中不能使用数据库事务控制语句,如:commit、rollback、savepoint语句;

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

(5)、触发器中不能使用lang、lang row类型;

(6)、触发器可以参照lob类型类的列值,但不能通过:new 来修改lob列中的值;

(6)、触发器所涉及的表收到表约束的限制

Oracle基础 触发器的更多相关文章

  1. Oracle基础<5>--触发器

    一.触发器 触发器是当特定事件出现时自动执行的代码块.比如,每次对员工表进行增删改的操作时,向日志表中添加一条记录.触发器和存储过程是由区别的:触发器是根据某些条件自动执行的,存储过程是手动条用的. ...

  2. 蜗牛—ORACLE基础之触发器学习(三)

    版权声明:本文为大腰子原创文章,如若转载,请标明原地址. https://blog.csdn.net/u010071361/article/details/30037215 建立一个触发器, 当职工表 ...

  3. Oracle基础学习笔记

    Oracle基础学习笔记 最近找到一份实习工作,有点头疼的是,有阶段性考核,这...,实际想想看,大学期间只学过数据库原理,并没有针对某一数据库管理系统而系统的学习,这正好是一个机会,于是乎用了三天时 ...

  4. ORACLE| ORACLE基础语法汇总

    创 ORACLE| ORACLE基础语法汇总 2018-07-18 16:47:34 YvesHe 阅读数 9141更多 分类专栏: [数据库]   版权声明:本文为博主原创文章,遵循CC 4.0 B ...

  5. oracle基础教程(8)oracle修改字符集

    oracle基础教程(8)oracle修改字符集 1.用dba连接数据库 -->sqlplus / as sysdba 2.查看字符集 -->SELECT parameter, value ...

  6. 图说Oracle基础知识(一)

    本文主要对Oralce数据库操作的基础知识进行一下梳理,以便进行归纳总结.适用于未使用过Oracle数据库的读者,或需要学习Oracle数据库方面的基础知识.如有不足之处,还请指正. 关于SQL介绍的 ...

  7. Oracle 基础学习笔记

    知识点 一.登陆数据库: 登陆数据库: sqlplus system/oracle123456 二.新建用户.授权(连接数据库.创建表.表空间.查询某用户下的表) 语法: create user [用 ...

  8. oracle基础教程oracle客户端详解

    oracle基础教程oracle客户端工具详解 参考网址:http://www.oraclejsq.com/article/010100114.html 该教程介绍了oracle自带客户端sqlplu ...

  9. Oracle基础 表分区

    Oracle基础 表分区 一.表分区 (一)表分区的分类 1.范围分区(range) 2.散列分区(hash) 3.列表分区(list) 4.复合分区:范围-哈希(range-hash).范围-列表( ...

  10. Oracle基础了解

    数据库: 关系型数据库 select * from 表名 非关系型数据库(做不到复杂查询) 以对象的形式进行存储 {"aaa":"ccc"}---键值对 ora ...

随机推荐

  1. 理解S12(X)架构中的地址映射方案

    目录 1. 介绍 2. CPU 本地地址 3. 分页窗口 4. 内存页 5. 控制各个对象在内存中放置的位置 介绍 在一个S12或S12X架构中,很有必要分清楚两种类型的内存地址:banked和non ...

  2. Kali安装到移动硬盘或者U盘中~Linux系通用方法(包括Android)

    0.1.保证这个服务必须启动(虚拟机服务最好都启动) 0.2.看看U盘接口类型是否对应 1.安装第一步 2.安装第二步,选择kali镜像 3.设置存放位置(上面的名字无所谓,最后不会用它的,虚拟机只是 ...

  3. css3文件树

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  4. 组合数问题(NOIP2016)

    原题传送门 这题啊. 裸的杨辉三角. 预处理杨辉三角和答案即可 下面贴代码 #include<iostream> #include<cstdio> #include<al ...

  5. linux的文件布局

    /bin---权限为 rwxr-xr-x 所有者为root/root 用户bin最先进入的工作目录就是这里.这里放置的是执行目录,但是特殊在这里的命令可以被一般用户使用(root更能使用).例如 ca ...

  6. Appium+python自动化12-appium元素定位【转载】

    前言 appium定位app上的元素,可以通过id,name.class这些属性定位到 一.id定位 1.appium的id属性也就是通过UI Automator工具查看的resource-id属性

  7. 洛谷 P1064 金明的预算方案【DP/01背包-方案数】

    题目背景 uim神犇拿到了uoi的ra(镭牌)后,立刻拉着基友小A到了一家--餐馆,很低端的那种. uim指着墙上的价目表(太低级了没有菜单),说:"随便点". 题目描述 不过ui ...

  8. POJ 1833 排列【STL/next_permutation】

    题目描述: 大家知道,给出正整数n,则1到n这n个数可以构成n!种排列,把这些排列按照从小到大的顺序(字典顺序)列出,如n=3时,列出1 2 3,1 3 2,2 1 3,2 3 1,3 1 2,3 2 ...

  9. FZU-2214 Knapsack problem(DP使用)

    Problem 2214 Knapsack problem Accept: 863    Submit: 3347Time Limit: 3000 mSec    Memory Limit : 327 ...

  10. cannot be cast to javassist.util.proxy.Proxy

    工程lib冲突 javassist-3.18.1-GA.jar javassist-3.11.0.GA.jar 删除一个