Oracle触发器

本文介绍了Oracle数据库中的触发器,这是一种在特定事件(如DML或DDL操作)发生时自动执行的存储过程。触发器无法直接调用,主要用于实现复杂业务逻辑。文章详细讲解了触发器的类型,包括行级触发器(对每行操作触发一次)、语句级触发器(影响多行数据触发一次)以及INSTEAD OF触发器,并提供了相应的语法和示例。同时,还阐述了如何启用、禁用和删除触发器的操作方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

触发器

  • 触发器是当特定事件出现时自动执行的存储过程

  • 特定事件可以是执行更新的DML语句和DDL语句

  • 触发器不能被显式调用

  • 触发器的功能:

      自动生成数据
      自定义复杂的安全权限
      提供审计和日志记录
      启用复杂的业务逻辑
    

触发器的组成部分:

触发器语句(事件)
 定义激活触发器的 DML 事件和 DDL 事件
 触发器限制
执行触发器的条件,该条件必须为真才能激活触发器
触发器操作(主体)
包含一些 SQL 语句和代码,它们在发出了触发器语句且触发限制的值为真时运行
  • 语法:
CREATE [OR REPLACE] TRIGGER trigger_name
AFTER | BEFORE | INSTEAD OF
[INSERT] [[OR] UPDATE [OF column_list]] 
[[OR] DELETE]
ON table_or_view_name
[REFERENCING {OLD [AS] old / NEW [AS] new}]
[FOR EACH ROW]
[WHEN (condition)]
pl/sql_block;

例子:

--创建一个触发器,每删除student表一条记录触发一次,并且输出删除的记录编号
create or replace trigger student_trigger--触发器名称
after --后置触发器,before、instead of、after
delete --删除操作,insert、delete、update
on student--作用在student表上,还可以在视图上
for each row--每一行都触发,也可以在语句级上
declare 
begin
  --:old指删除的记录行对象,:new 指新增的行对象,只能用在行级触发器中,不能用在语句级触发器
  dbms_output.put_line('删除的记录编号:'||:old.id);
end;
--1、创建触发器,只有在周一到周五上午9点到下午5点之间才可以对表student进行增删改操作

--2、创建触发器,创建一个日志记录表student_op_log(主键id数字类型,操作类型op_type字符串类型,
--描述信息remark字符串类型,操作时间create_time当前系统时间),
--用来存放对student表增删改操作日志记录

触发器类型

行级触发器
每影响一行就触发一次(加for each row)
例子1:

--创建一个触发器,每删除student表一条记录触发一次,并且输出删除的记录编号
create or replace trigger student_trigger--触发器名称
after --后置触发器,before、instead of、after
delete --删除操作,insert、delete、update
on student--作用在student表上,还可以在视图上
for each row--每一行都触发,也可以在语句级上
declare 
begin
--:old指删除的记录行对象,:new 指新增的行对象,只能用在行级触发器中,不能用在语句级触发器
  dbms_output.put_line('删除的记录编号:'||:old.id);
end;

例子2:

--创建一个触发器 ,分别在新增,修改,删除student表数据触发一次
create or replace trigger test_trigger
after
insert or update or delete
on student
for each row
declare

begin
  if inserting then
    dbms_output.put_line('新增操作');
    dbms_output.put_line('编号:'||:new.id||',姓名:'||:new.name);
    elsif updating then 
    dbms_output.put_line('修改操作');
    dbms_output.put_line('旧密码:'||:old.password||',新密码:'||:new.password);
    elsif deleting then
    dbms_output.put_line('删除操作');
    dbms_output.put_line('编号:'||:old.id);    
    else 
    dbms_output.put_line('其他操作');
  end if;
end;

例子3:

--创建前置触发器,一般用作校验
create or replace trigger check_trigger
before
insert or update or delete
on student
for each row
  declare
  
  begin
  if inserting then 
    if :new.sex not in(0,1) then
      raise_application_error(-20001,'性别只能为0或1');
    end if;
    dbms_output.put_line('编号:'||:new.id||',姓名:'||:new.name);
    elsif updating then
    if :new.age not between 18 and 120 then
      raise_application_error(-20002,'年龄范围错误,只能在18-120之间');
      end if;
    dbms_output.put_line('旧年龄:'||:old.age||',新年龄:'||:new.age);      
  
    elsif deleting then
    if :old.id  between 100 and 200 then
      raise_application_error(-20003,'删除错误,不能删除编号在100-200之间的记录');
      end if;
      dbms_output.put_line('删除编号:'||:old.id);   
      else 
      dbms_output.put_line('其他操作');   
        end if;
         end;

语句级触发器
影响多行数据只触发一次
INSTEAD OF 触发器
语法:

SQL> CREATE OR REPLACE TRIGGER upd_ord_view
          INSTEAD OF UPDATE ON ord_view
          FOR EACH ROW
          BEGIN
     		UPDATE order_master
          SET vencode=:NEW.vencode 
		WHERE orderno = :NEW.orderno;
		DBMS_OUTPUT.PUT_LINE(‘已激活触发器');
          END;
----instead of 触发器
--创建视图
create or replace view v_emp_dept
as
select e.employee_id,e.first_name,e.salary,d.department_id,d.department_name
from emp e,dept d
where e.department_id=d.department_id(+)
order by e.employee_id;
--查询视图,不能直接对视图数据进行操作
select * from v_emp_dept;
--添加视图,不能直接对视图添加数据
insert into v_emp_dept(employee_id,first_name,salary,department_id,department_name) values(301,'张三',10000,500,'软件');
--修改视图,不能直接对视图数据进行修改
update v_emp_dept v set v.department_name='lala' where v.employee_id=301; 
--删除视图数据,不能直接对视图数据进行删除
delete v_emp_dept v where v.employee_id=301;
--创建触发器,对视图进行增删改
--原理:实际上是通过程序逻辑对真实表数据进行增删改,只是对外部调用者透明,感觉好像是直接可以对视图进行操作。
create or replace trigger view_trigger
instead of --只能用在视图上
insert or update or delete 
on v_emp_dept--视图名称
for each row
  begin
    if inserting then 
      insert into emp(employee_id,first_name,salary,department_id)
      values(:new.employee_id,:new.first_name,:new.salary, :new.department_id);
      insert into dept(department_id,department_name) values(:new.department_id,:new.department_name);
      dbms_output.put_line('添加成功');
    elsif updating then
    update emp e
       set e.first_name    = :new.first_name,
           e.salary        = :new.salary,
           e.department_id = :new.department_id
     where e.department_id = :new.department_id;
     update dept d
        set d.department_name = :new.department_name
      where d.department_id = :new.department_id;
            dbms_output.put_line('修改成功');
    elsif deleting then
      delete emp e where e.employee_id=:old.employee_id;
            dbms_output.put_line('删除成功');
    end if;
  end;

模式触发器
语法:

SQL> CREATE OR REPLACE TRIGGER log_drop_obj
AFTER DROP ON SCHEMA
BEGIN
  INSERT INTO dropped_obj
  VALUES( ORA_DICT_OBJ_NAME, 
          ORA_DICT_OBJ_TYPE, SYSDATE);
END;

例子:

--创建用户模式级触发器,对对象结构进行操作ddl语句
create or replace trigger schema_trigger
after
drop or create or alter--支持创建、修改、删除
on schema--用户模式级别
begin
  dbms_output.put_line('对象拥有者:'||ora_dict_obj_owner);
  dbms_output.put_line('当前登录用户:'||ora_login_user);
  dbms_output.put_line('对象名称:'||ora_dict_obj_name);
  dbms_output.put_line('对象类型'||ora_dict_obj_type);
  dbms_output.put_line('数据库实例名称:'||ora_database_name);  
  dbms_output.put_line('数据库ip地址'||ora_client_ip_address);
  dbms_output.put_line('创建时间'||to_char(sysdate,'yyyy-MM-dd hh24:mi:ss'));

end;
--测试触发器
drop table tex;
create table tex as select * from student where 1=2;

启用、禁用和删除触发器
禁用触发器语法:alter trigger 触发器名 disable;
启用触发器:SQL> ALTER TRIGGER 触发器名 ENABLE;
删除触发器:SQL> DROP TRIGGER 触发器名;

--禁用触发器        
  alter trigger student_trigger disable;
  alter trigger test_trigger disable;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值