Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Oracle触发器-imooc

Oracle触发器-imooc

作者头像
chenchenchen
发布于 2023-01-30 09:20:49
发布于 2023-01-30 09:20:49
1.4K0
举报
文章被收录于专栏:chenchenchenchenchenchen

一、触发器相关概念及语法

1-1概述

  • 什么是触发器
  • 触发器的应用场景
  • 触发器的语法
  • 触发器的类型
  • 案例

1-2触发器的概念和第一个触发器

数据库触发器是一个与表相关联的,存储的PL/SQL 语句。

每当一个特定的数据操作语句(insert update delete)在指定的表上发出时,Oracle自动执行触发器中定义的语句序列。

命令窗口中实现个简单的例子:

当员工表中新增一条记录后,自动打印“成功插入新员工”

create or replace trigger saynewemp   after insert on emp     for each row declare   -- local variables here begin

     dbms_output.put_line('新增员工成功');

end ;

/

命令窗口实现效果:

SQL> set serveroutput on; SQL> insert into emp(empno,ename,sal,deptno) values(8889,'chenyy',1.2,10); 新增员工成功 1 row inserted

SQL> commit; Commit complete

1-3触发器的应用场景

  • 复杂的安全性检查
  • 数据的确认
  • 数据库审计
  • 数据的备份和审计

1-4触发器的语法

CREATE [OR REPLACE] TRIGGER trigger_name {BEFORE | AFTER } {INSERT | DELETE | UPDATE [OF column [, column …]]} [OR {INSERT | DELETE | UPDATE [OF column [, column …]]}...] ON [schema.]table_name | [schema.]view_name [REFERENCING {OLD [AS] old | NEW [AS] new| PARENT as parent}] [FOR EACH ROW  [WHEN condition] ] PL/SQL_BLOCK | CALL procedure_name; 其中:

BEFORE 和AFTER,前触发是在执行事件之前触发,后触发是在执行事件之后触发。

FOR EACH ROW选项说明触发器为行触发器。当省略FOR EACH ROW 选项时,BEFORE 和AFTER 触发器为语句触发器,而INSTEAD OF 触发器则只能为行触发器 

REFERENCING 子句说明相关名称,在行触发器的PL/SQL块和WHEN 子句中可以使用相关名称参照当前的新、旧列值,默认的相关名称分别为:old和:new。触发器的PL/SQL块中应用相关名称时,必须在它们之前加冒号(:),但在WHEN子句中则不能加冒号。

WHEN 子句说明触发约束条件。Condition 为一个逻辑表达时,其中必须包含相关名称,而不能包含查询语句,也不能调用PL/SQL 函数。WHEN 子句指定的触发约束条件只能用在BEFORE 和AFTER 行触发器中,不能用在INSTEAD OF 行触发器和其它类型的触发器中。

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

触发器的类型

行触发器要求当一个DML语句操作影响数据库中的多行数据时,对于其中的每个数据行,只要它们符合触发约束条件,均激活一次触发器; 在行级触发器中,使用:old 和:new 伪记录变量,识别值的状态

语句触发器将整个语句操作作为触发事件,当它符合约束条件时,激活一次触发器。

每张表最多可建立12 种类型的触发器:

BEFORE INSERT BEFORE INSERT FOR EACH ROW AFTER INSERT AFTER INSERT FOR EACH ROW

BEFORE UPDATE BEFORE UPDATE FOR EACH ROW AFTER UPDATE AFTER UPDATE FOR EACH ROW

BEFORE DELETE BEFORE DELETE FOR EACH ROW AFTER DELETE AFTER DELETE FOR EACH ROW 

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

DML触发器的限制: CREATE TRIGGER语句文本的字符长度不能超过32KB; 触发器体内的SELECT 语句只能为SELECT … INTO …结构,或者为定义游标所使用的SELECT 语句。 触发器中不能使用数据库事务控制语句 COMMIT; ROLLBACK, SVAEPOINT 语句; 由触发器所调用的过程或函数也不能使用数据库事务控制语句; 触发器中不能使用LONG, LONG RAW 类型; 触发器内可以参照LOB 类型列的列值,但不能通过 :NEW 修改LOB列中的数据;

二、触发器应用

2-1触发器应用一 复杂的安全性检查

禁止在非工作时间插入数据

在命令行查询时间

SQL> select sysdate from dual; SYSDATE ----------- 2019/4/26 1

SQL> select to_char(sysdate,'day') from dual; TO_CHAR(SYSDATE,'DAY') ---------------------- 星期五

SQL> select to_number(to_char(sysdate,'hh24')) from dual; TO_NUMBER(TO_CHAR(SYSDATE,'HH2 ------------------------------                             14

在程序/命令窗口编译触发器

/** 非工作时间(星球六 星期日, 非9点~18点的区间) 禁止写入数据

语句级触发器:不管插入了多少条数据,没有必要对每一行数据都进行校验,只要不在这个时间段内,都不让插入。 */

create or replace trigger addStaffCheck before insert on emp begin     --判断当前时间是否是双休或者是上午九点到下午6点     if to_char(sysdate,'day') in ('星期六','星期天') or     to_number(to_char(sysdate,'hh24')) not between 9 and 18 then     --禁止插入,抛出错误码和错误信息。     raise_application_error(-20001,'禁止在非工作时间插入新员工!');     end if; end;

raise_application_error(error_number,message[,[truefalse]]); 用于在plsql使用程序中自定义错误消息。 其中 error_number用于定义错误码,必须在-20000到-20999之间的负整数; message用于指定错误消息,并且该消息的长度无法超过2048字节; 该异常只好在数据库端的子程序(流程、函数、包、触发器)中运用,而无法在匿名块和客户端的子程序中运用。 

触发器应用二 数据确认

工资不能越涨越少,涨后的薪水不能低于涨前的薪水

分析: 首先确认下触发器的类型, 因为需要对每一条数据进行确认,所以是个行级触发器。 需要for each row

create or replace trigger salary_check before update on emp for each row begin  --:new 表示更新后的列 :old 表示更前的列   if :new.sal<:old.sal then      raise_application_error(-20001,'涨后的薪水不能低于涨前的薪水!涨前的薪水为'||:old.sal||'涨后的薪水为'||:new.sal);   end if; end;

/

触发器应用三 数据库审计 创建基于值的触发器:给员工涨工资,当加薪超过1000块钱时审计该员工的信息

第一步:创建审计表信息,用于保存审计信息 create table audit_info(infomation varchar(200)); 第二步创建审计信息触发器 create or replace trigger salary_audit  after update  on emp for each row begin    --涨薪超过1000元进行审计     if :new.sal - :old.sal > 1000 then        dbms_output.put_line('工资增加超过1000,进入审计');         insert into audit_info(infomation) values('员工号为:'||:new.empno||'工资涨到'||:new.sal);     end if; end;

2-4触发器应用四 数据的备份和同步

使用触发器实现对emp的备份(给员工涨完工资后自动更新新的数据到备份表中)

第一步 创建emp的备份表 create table emp_bak as select * from emp; 第二步 创建备份使用到触发器

create or replace trigger salary_sync after update on emp for each row --给员工涨完工资后,自动备份到备份表中 begin     update emp_back set sal=:new.sal where empno=:new.empno;     dbms_output.put_line('已同步更新'); end;

oracle中还有个利用快照备份,是异步的。 而利用触发器,是同步的。

其他

建立一个触发器, 当职工表 emp 表被删除一条记录时,把被删除记录写到职工表删除日志表中去 CREATE TABLE emp_delinfo AS SELECT * FROM EMP WHERE 1=2; CREATE OR REPLACE TRIGGER emp_del    AFTER DELETE     ON scott.emp    FOR EACH ROW    BEGIN    --将修改前数据插入到日志记录表 ,以供监督使用。    INSERT INTO emp_delinfo(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 );     dbms_output.put_line('删除成功'); END;

DELETE emp WHERE empno=7788; DROP TABLE emp_delinfo; DROP TRIGGER emp_del;

限定只对部门号为80的记录进行行触发器操作。 CREATE OR REPLACE TRIGGER tr_emp_sal_comm BEFORE UPDATE OF salary, commission_pct        OR DELETE ON HR.employees FOR EACH ROW WHEN (old.department_id = 80) BEGIN  CASE      WHEN UPDATING ('salary') THEN         IF :NEW.salary < :old.salary THEN

           RAISE_APPLICATION_ERROR(-20001, '部门80的人员的工资不能降');         END IF;      WHEN UPDATING ('commission_pct') THEN

        IF :NEW.commission_pct < :old.commission_pct THEN            RAISE_APPLICATION_ERROR(-20002, '部门80的人员的奖金不能降');         END IF;      WHEN DELETING THEN           RAISE_APPLICATION_ERROR(-20003, '不能删除部门80的人员记录');      END CASE; END;

更多详细介绍http://www.cnblogs.com/huyong/archive/2011/04/27/2030466.html

来源http://www.cnblogs.com/huyong/archive/2011/04/27/2030466.html,http://www.imooc.com/article/263650

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-04-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
实验验证sys和system用户全库导出的区别
我们在做逻辑数据泵全库导出的时候,有两种流行的写法,一种是sys用户导出,一种是使用system用户导出。 现在想知道二者之间有什么区别?实验验证之前不妨先思考一下:
Alfred Zhao
2022/05/06
4410
快速学习Oracle-触发器
数据库触发器是一个与表相关联的、存储的 PL/SQL 程序。每当一个特定的数据操作语句(Insert,update,delete)在指定的表上发出时,Oracle 自动地执行触发器中定义的语句序列。
cwl_java
2019/12/19
6140
Oracle触发器用法实例详解
详细的介绍可以参考网上的资料,简单的说就是语句级的触发器可以在某些语句执行前或执行后被触发。而行级触发器则是在定义的了触发的表中的行数据改变时就会被触发一次。
星哥玩云
2022/08/17
1.2K0
Oracle触发器用法实例详解
​oracle 笔记
一、 oracle介绍 ORACLE 数据库系统是美国 ORACLE 公司(甲骨文)提供的以分布式数据库为核心的一组 软件产品,是目前最流行的客户/服务器(CLIENT/SERVER)或 B/S 体系结构的数据库之一。 比如SilverStream 就是基于数据库的一种中间件。ORACLE 数据库是目前世界上使用最为广泛的数据 库管理系统,作为一个通用的数据库系统,它具有完整的数据管理功能; 作为一个关系数据库, 它是一个完备关系的产品;作为分布式数据库它实现了分布式处理功能。但它的所有知识,只 要在一种机型上学习了ORACLE 知识,便能在各种类型的机器上使用它。
千羽
2021/07/20
9530
​oracle 笔记
Oracle总结【PLSQL学习】
PLSQL介绍 PLSQL是Oracle对SQL99的一种扩展,基本每一种数据库都会对SQL进行扩展,Oracle对SQL的扩展就叫做PLSQL… SQL99是什么 (1)是操作所有关系型数据库的规则 (2)是第四代语言 (3)是一种结构化查询语言 (4)只需发出合法合理的命令,就有对应的结果显示 SQL的特点 (1)交互性强,非过程化 (2)数据库操纵能力强,只需发送命令,无需关注如何实现 (3)多表操作时,自动导航简单,例如: select emp.empno,emp.sal,dept.dname fr
Java3y
2018/03/15
2.5K0
Oracle总结【PLSQL学习】
Oracle-trigger触发器解读
每当一个特定的数据操作语句(insert update delete)在指定的表上发出时,Oracle自动执行触发器中定义的语句序列。
小小工匠
2021/08/16
1.2K0
Oracle触发器详细讲解
CREATE OR REPLACE TRIGGER scott_trigger BEFORE DDL ON SCHEMA BEGIN   RAISE_APPLICATION_ERROR(-20008,'禁止scott用户的所有ddl操作'); END;create sequence myseq;
星哥玩云
2022/08/17
1K0
Oracle触发器详细讲解
基于 dbms_redefinition 在线重定义表
      Oracle 支持在线重定义表,也就是说我们可以在修改表结构(DDL)的同时进行相关的DQL、DML操作,使得前端的DML根本感觉不到表结构实际上已经发生了变化,对于用户而言是完全透明的。当然在线重定义期间,前端性能会稍微有所下降。Oracle提供的重定义包dbms_redefinition即是用与完成此操作。其实质是Oracle使用了智能物化视图及物化视图日志的方式。在对象结构重组期间,表现为一个本地对象的复制,重组期间发生的任何变化都会被刷新到最新。
Leshami
2018/08/13
1K0
基于 dbms_redefinition 在线重定义表
Oracle学习笔记四
在写java程序中有集合的概念,那么在pl/sq中也会用到多条记录,这时候我们就要用到游标,游标可以存储查询返回的多条数据。
Kevin_Zhang
2018/09/20
1.4K0
Oracle学习笔记四
PL/SQL --> DML 触发器
何谓触发器?简言之,是一段命名的PL/SQL代码块,只不过该代码块在特定的条件下被触发并且执行。对于这样的代码我们称之为触发器
Leshami
2018/08/07
1.6K0
ORACLE触发器具体解释
触发器是很多关系数据库系统都提供的一项技术。在ORACLE系统里,触发器类似过程和函数,都有声明,运行和异常处理过程的PL/SQL块。
全栈程序员站长
2022/07/13
1.2K0
oracle的行级触发器使用
行级触发器: 当触发器被触发时,要使用被插入、更新或删除的记录中的列值,有时要使用操作前、后列的值. :NEW 修饰符访问操作完成后列的值 :OLD 修饰符访问操作完成前列的值 例1: 建立一个触发器
庞小明
2018/04/18
1.7K0
oracle的行级触发器使用
day44_Oracle学习笔记_03
先去Oracle官网去下载最新版本的sqldeveloper,下载地址:https://www.oracle.com/technetwork/developer-tools/sql-developer/downloads/index.html 得到2个zip压缩包,如下图所示:
黑泽君
2018/10/11
1.8K0
day44_Oracle学习笔记_03
【MySQL高级】视图与触发器
视图(View)是一种虚拟存在的表。视图并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。通俗的讲,视图就是一条SELECT语句执行后返回的结果集。所以我们在创建视图的时候,主要的工作就落在创建这条SQL查询语句上。
陶然同学
2023/02/24
5860
【MySQL高级】视图与触发器
Oracle应用实战八(完结)——存储过程、函数+对象曹组
游标 在写java程序中有结果集的概念,那么在pl/sql中也会用到多条记录,这时候我们就要用到游标,游标可以存储查询返回的多条数据。 游标可以理解为是PL/SQL中的结果集,我们通过游标可以提取结果
Java帮帮
2018/03/19
1.9K0
Oracle应用实战八(完结)——存储过程、函数+对象曹组
pl/sql编程语言
ena emp.ename%type; --引用型变量,直接取出emp表中ename的类型给ena
主机优惠
2019/06/20
7K0
ORACLE触发器(trigger)的使用
触发器是一种在事件发生时隐式地自动执行的PL/SQL块,不能接受参数,不能被显式调用
全栈程序员站长
2022/09/13
1.2K0
ORACLE触发器(trigger)的使用
触发器学习笔记(:new,:old用法)
转载自:https://www.2cto.com/database/201301/186334.html
qubianzhong
2019/06/26
9880
Oracle数据库之第四篇
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
海仔
2019/10/22
9760
PL/SQL 编程(三 )程序包和包体,触发器,视图,索引
一、程序包和包体 程序包(package):存储在数据库中的一组子程序、变量定义。在包中的子程序可以被其它程序包或子程序调用。但如果声明的是局部子程序,则只能在定义该局部子程序的块中调用该局部子程序。 它具有面向对象程序设计语言的特点,是对这些PL/SQL 程序设计元素的封装。包类似于JAVA语言中的类,其中变量相当于类中的成员变量,过程和函数相当于类方法。 create or replace package stuinfo as type stucur is ref cursor; procedu
二十三年蝉
2018/02/28
1.1K0
相关推荐
实验验证sys和system用户全库导出的区别
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档