设为首页 收藏本站
查看: 2655|回复: 0

[经验分享] oracle pl/sql之触发器(trigger)

[复制链接]

尚未签到

发表于 2018-9-12 09:39:18 | 显示全部楼层 |阅读模式
  一.oracle触发器介绍
  触发器在数据库里以独立的对象存储,它与存储过程和函数不同的是,存储过程与函数需要用户显示调用才执行,而触发器是由一个事件来启动运行。即触发器是当某个事件发生时自动地隐式运行。并且,触发器不能接收参数。所以运行触发器就叫触发或点火(firing)。ORACLE事件指的是对数据库的表进行的INSERT、UPDATE及DELETE操作或对视图进行类似的操作。ORACLE将触发器的功能扩展到了触发ORACLE,如数据库的启动与关闭等。所以触发器常用来完成由数据库的完整性约束难以完成的复杂业务规则的约束,或用来监视对数据库的各种操作,实现审计的功能。
  二.触发器语法
  触发器由触发事件,触发条件和触发操作三部分组成。
  (1)触发事件
  指引起触发器被触发的SQL语句,数据库事件或者用户事件。
  具体触发事件:
  启动和关闭数据库实例
  oracle错误消息
  用户登录和断开会话
  特定表和视图的DML操作
  在任何方案上的DDL操作
  (2)触发条件(可选)
  指使用when子句指定一个BOOLEAN表达式,当布尔表达式为TRUE时,会自动执行触发器相应代码。
  (3)触发操作
  指包含SQL语句和其他执行代码的PL/SQL块。
  限制条件:
  1.触发器代码不能超过32K。
  2.触发器代码中不能使用long or long raw数据类型。
  ###基于视图的触发器instead of触发器
  ###DML触发器包括语句触发器和行触发器
  DML需要指定触发时机(before|after),触发事件(insert,update,delete),表名,触发类型,触发条件,触发操作。
  触发时机:用于指定触发器的触发时间。before表示执行DML操作之前触发触发器。
  触发事件:用于指定导致触发器执行DML操作。
  表名:用于指定DML操作所对应的表。
  触发类型:用于指定当触发事件发生之后,需要执行几次触发操作。
  触发条件:用于指定执行触发器的条件,只有条件为TRUE时才会执行触发器代码。
  触发操作:用于指定触发器执行代码。
  三.触发器类型
  1.语句触发器
  当审计DML操作,或者确保DML操作安全执行时,可以使用语句触发器。语句触发器不能记录列数据的变化。
  语法:
  create or replace trigger trigger_name
  timing event1 [or event2 or event3]
  on table_name
  pl/sql block;
  (1)before语句触发器
  //禁止工作人员在周一改变雇员信息
create or replace trigger tr_change_emp  
before insert or update or delete
  
---insert update delete三种操作触发触发器
  
on emp
  
begin
  
if to_char(sysdate,'DY','nls_date_language=AMERICAN') IN ('MON') then
  
---自定义错误输出
  raise_application_error(-20001,'You can not change employee infor.');
  
end if;
  
end;
  当触发器中同时包含多个触发事件时(insert,update,delete).区分具体的触发事件,可以使用3个为此:
  inserting,updating,deleting
create or replace trigger tr_change_emp  
before insert or update or delete
  
on emp
  
begin
  if to_char(sysdate, 'DY', 'nls_date_language=AMERICAN') IN ('MON') then
  case
  when inserting then
  raise_application_error(-20001, 'You can not insert employee infor.');
  when updating then
  raise_application_error(-20002, 'You can not update employee infor.');
  when deleting then
  raise_application_error(-20003, 'You can not delete employee infor.');
  end case;
  
end if;
  
end;
  (2)after语句触发器
  //审计emp表上insert,update,delete操作次数
  思路
  1.首先创建一个统计表t_audit,用于统计针对emp表的insert,update,delete次数
  2.统计表中的第一个字段names,可以支持对多个表进行统计,每个表为一行,有insert次数,update次数,delete次数
  3.添加if语句检测,如果某个表是首次进行统计,则在统计表中新建一条记录,并把此表的各项次数初始化为0
---首先创建表  
create table t_audit(names varchar2(30) not null primary key,insert_count number,update_count number,delete_count number,start_date date,end_date date);
  
---创建触发器
  
create or replace trigger tr_audit_emp
  
after insert or update or delete on emp
  
---on emp表明针对emp表有效
  
declare
  v_tmp number;
  
begin
  
---
  select count(*) INTO v_tmp from t_audit where names = 'EMP';
  
if v_tmp = 0 then
  insert into t_audit values ('EMP', 0, 0, 0, sysdate, null);
  
end if;
  
case
  
when inserting then
  update t_audit set insert_count = insert_count + 1 where names = 'EMP';
  
when updating then
  update t_audit set update_count = update_count + 1 where names = 'EMP';
  
when deleting then
  update t_audit set delete_count = delete_count + 1 where names = 'EMP';
  
end case;
  
end;
  2.行触发器
  行触发器是指执行DML操作时,每作用一行就触发一次的触发器。审计数据变化时,可以使用行触发器。
  语法:
  create or replace trigger trigger_name
  timing event1 [or event2 or event3]
  on table_name
  [reference OLD AS old|NEW AS new]
  FOR EACH ROW
  [when condition]
  PL/SQL block;
  reference:用于指定新,旧数据的方式。默认情况下OLD修饰符引用旧数据,使用NEW修饰符引用新数据。
  FOR EACH ROW:表示建立行触发器
  (1)before行触发器
  //确保雇员工资不低于其原有工资
create or replace trigger tr_update_sal  
before update of sal on emp
  
for each row
  
begin
  
if :NEW.sal < :OLD.sal then
  raise_application_error(-20001,'salary up');
  
end if;
  
end;
  (2)
  //审计雇员工资的变化
--首先创建用于统计的表  
CREATE TABLE "T_AUDIT_SALARY"
  ("ENAMES" VARCHAR2(50),
  
"OLDSAL" NUMBER(7,2),
  
"NEWSAL" NUMBER(7,2),
  
"CREATE_DATE" TIMESTAMP
  );
  
--创建触发器,after后跟触发事件
  
create or replace trigger tr_audit_salary
  
after update of sal on emp
  
for each row
  
--after update of sal on emp指定触发的字段(sal),以及对此字段的操作(update)
  
declare
  v_tmp number;
  
begin
  
--if判断用于新增一条统计信息,:old.ename为emp表中雇员姓名,当首次更新emp表中某一位雇员姓名时,把此雇员姓名(:old.ename)作为一行新增到统计表中
  select count(*) into v_tmp from t_audit_salary where enames=:old.ename;
  
if v_tmp =0 then
  insert into t_audit_salary values(:old.ename,:old.sal,:new.sal,sysdate);
  
else
  update t_audit_salary set oldsal=:old.sal,newsal=:new.sal,create_date =sysdate
  
where enames=:old.ename;
  
end  if;
  
end;
  3.系统事件触发器
  系统事件触发器指基于oracle系统事件所建立的触发器,提供了跟踪系统内或数据库变化的机制。
  常见的系统事件属性函数:
  ora_client_ip_address:用于返回客户端的IP地址。
  ora_database_name:用于返回当前数据库名。
  ora_login_user:用于返回登录用户名。
  ora_sysevent:用于返回触发触发器的系统事件名。
  //记录用户登录和退出
  首先创建记录表
create table t_login(username varchar2(50),logon_date date,logoff_date date,address varchar2(15));  创建登陆数据库事件触发器
create or replace trigger tr_login  
after logon on database
  
begin
  insert into t_login(username,logon_date,address)
  
values(ora_login_user,sysdate,ora_client_ip_address);
  
end;
  创建退出数据库触发器
create or replace trigger tr_logoff  
before logoff on database
  
--before操作说明是在退出数据库之前触发
  
begin
  insert into t_login(username,logoff_date)
  
values(ora_login_user,sysdate);
  
end;
  //记录数据库启动和关闭
--首先创建记录表  
create table t_sysevent(events varchar2(50),create_date timestamp);
  
--数据库启动触发器
  
create or replace trigger tr_startup
  
after startup on database
  
begin
  insert into t_sysevent values(ora_sysevent,sysdate);
  
end;
  
--数据库关闭触发器
  
create or replace trigger tr_shutdown
  
before shutdown on database
  
begin
  insert into t_sysevent values(ora_sysevent,sysdate);
  
end;
  四.管理触发器
  --查看作用与某张表上的所有触发器
  select TRIGGER_NAME,table_name,status from user_triggers where table_name='EMP';
  ---禁止某个触发器
  alter trigger trigger_name disable;
  ---启用触发器
  alter trigger TR_STARTUP enable;



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-573193-1-1.html 上篇帖子: oracle pl/sql之包(package) 下篇帖子: oracle 用户解锁
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表