Oracle触发器详解


1、触发器是指存在数据库中,被隐含执行的存储过程,可以支持dml触发器,
   还支持基于系统事件[启动数据库,关闭数据库,登录]和ddl操作建立触发器

----------------------
--触发器分类
----------------------
1、dml触发器 - insert、delete、update
2、ddl触发器 - create table|view ..、drop ..

----------------------
--语法介绍
----------------------
create[or replace] trigger trigger_name
{before|after}
{insert|delete|update[of column[,column ....]]}
on[schema.]table_name
[for each row]
[when condition]
begin
  tigger_body;
end;

------------------------------------------------
--dml触发器 - insert、delete、update
------------------------------------------------
--案例
1、当插入数据时,就提示添加记录信息
create or replace trigger mytrigger
after insert on scott.emp
begin
  dbms_output.put_line('添加一条记录');
end;

insert into emp(EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO)
values(7945,'jiji','zhonguo',7566,to_date('1980/12/17', 'yyyy/mm/dd'), 20000,1000,20);


2、在某张表修改多条数据的时候,提示 修改数据
create or replace trigger mytrigger
after update on scott.emp
begin
  dbms_output.put_line('修改了数据');
end;

3、--禁止工作人员在休息日改变员工信息
   开发人员可以建立before语句触发器,从而实现数据的安全
create or replace trigger mytrigger
before delete on scott.emp
begin
  if to_char(sysdate, 'day') in('星期日', '星期六', '星期五') then
    --dbms_output.put_line('对不起,休息日不能删除表');
    RAISE_APPLICATION_ERROR('-20001', '对不起,休息日不能删除员工'); --自定义错误
  end if;
end;

--特别说明
①、RAISE_APPLICATION_ERROR这个过程,是oracle提供的,可以传入两个参数
第一个:自定义的错误号 -20000~-20999
第二个:提示信息

4、--dml联合使用
create or replace trigger mytrigger
before insert or update or delete on scott.emp
begin
  case
    when inserting then
      RAISE_APPLICATION_ERROR(-20002, '请不要添加');
    when updating then
      RAISE_APPLICATION_ERROR(-20003, '请不要修改');
    when deleting then
      RAISE_APPLICATION_ERROR(-20004, '请不要删除');  
  end case;
end;

-----------------------
5、使用 :old 和 :new
-----------------------
问题:当触发器被触发时,要使用被插入、更新或删除的记录中的列值,有时要使用操作前、后列的值
-- :new 修饰符访问操作完成后列的值
-- :old 修饰符访问操作完成前列的值

特性    insert     update   delete
old     NULL       有效      有效
new     有效       有效      NULL

--案例
1、在修改emp表 雇员的薪水时,显示雇员工资修改前和修改后的值
2、如何确保在修改员工工资不能低于原有工资
create or replace trigger mytrigger
before update on scott.emp
for each row
begin
  if :new.sal<:old.sal then
     RAISE_APPLICATION_ERROR(-20005, '工资不能低于原有工资');
  else
    dbms_output.put_line('原有工资:'||:old.sal||'现在工资:'||:new.sal);
  end if;
end;

update emp set sal=3 where empno=7934;
update emp set sal=300 where empno=7934;


6、编写一个触发器,保证当用户在删除一张表记录的时候
   自动把删除的记录备份到另一张表中
create table emp_bak as select * from emp;

create or replace trigger mytrigger
before delete on scott.emp
for each row
begin
   insert into emp_bak(EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO)
values(:old.EMPNO,:old.ENAME,:old.JOB,:old.MGR,:old.HIREDATE,:old.SAL,:old.COMM,:old.DEPTNO);    
end;
   


------------------------------------------------
--ddl触发器 - create table|view ..、drop ..
------------------------------------------------
①为了记录系统所发生的ddl事件,应该建立一张表[ddl_event]用来存储相关信息
②注意需要使用system用户登录conn system/manager as sysdba;

--语法
create or replace trigger 触发器名
after ddl 方案名.schema --如:scott.schema
begin
  执行语句
end;

--案例
create table ddl_table(
  event varchar2(64),    --事件名
  username varchar2(64), --用户名
  ddl_time date          --时间
);

--创建触发器 可以记录某个用户进行的ddl操作
create or replace trigger ddl_triiger
after ddl on scott.schema
begin
  insert into ddl_table  --插入 事件名、当前用户、当前时间
  values(ora_sysevent, ora_login_user, sysdate);
end;


---------------------------------------
--系统触发器
---------------------------------------
--语法
create or replace trigger 触发器名
after[before] logon[logoff] on database
begin
  执行语句
end;

注意事项:
①需要建立在sys|system上
②由系统管理员来完成

--常用属性函数
  ora_client_ip_address 返回客户端的ip
  ora_database_name 返回数据库名
  ora_login_user 返回登录用户名
  ora_sysevent 返回触发触发器的系统事件名
  ora_des_encrypted_password 返回用户des(md5)加密后的密码

--创建表,用于保存用户登录或者退出的情况
create table log_table(
  username varchar2(20),  --登录名
  logon_time date,        --登录时间
  logoff_time date,       --退出时间
  address varchar2(20)    --登录地址
);

1、--登录触发器
create or replace trigger logon_trigger
after logon on database
begin
  insert into log_table(username,logon_time,address)
  values(ora_login_user, sysdate, ora_client_ip_address);
end;


2、--退出触发器
create or replace trigger logoff_trigger
before logoff on database
begin
  insert into log_table(username,logoff_time,address)
  values(ora_login_user, sysdate, ora_client_ip_address);
end;


---------------------------------------
--管理触发器
---------------------------------------
1、禁止触发器
   是指让触发器临时失效
   alter trigger 触发器名 disable;

2、激活触发器
   alter trigger 触发器名 enable;

3、禁止或是激活表的所有触发器
   alter table emp disable all triggers;(9i)
   alter table emp enable all triggers;(9i)

4、删除触发器
   drop trigger 触发器名
   
  

原文地址:https://www.cnblogs.com/qintangtao/p/2752065.html