Oracle触发器

本文介绍了Oracle触发器的基本原理,包括三种操作(delete, update, insert),两种临时表(:new, :old),两个时间点(after, before)以及行级和语句级触发器模式。触发器作为特殊存储过程,由数据库事件自动触发,主要用于增强数据完整性约束和业务规则。文中还讨论了创建触发器的语法,并给出具体案例,如限制特定用户进行删除、增加和修改操作,以及实现级联删除和使用标识列(序列+触发器)。" 117358627,8363722,内网穿透教程:从BadUSB到外网访问,"['内网穿透工具', '网络配置', '远程访问', '服务器管理', 'Web应用']

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

一、触发器(原理)

1.三种操作: delete update insert
2.两个临时表: :new :old
3.两个时间点: after before
4.两种重要模式: 行级 语句级
5.条件: when

二,什么是触发器?

1.触发器是一种特殊的存储过程;
2.触发器不能被直接调用,也不是手动启动,而是由事件来触发;–增删改
3.触发器经常用于加强数据的完整性约束和业务规则等。
4.触发器具备事务的功能。简单点说:触发器就是个开关,负责灯的亮与灭,你动了它就亮了。

三,创建触发器语法

create [or replace] trigger trigger_name
after|before|instead of                    --instead反向
[insert][[or] update [of 列列表]][[or] delete]
on table表或view                            --视图使用率 
[referencing{:old [as] old/:new [as] new}]  --引用新表老表
[for each row]                              --行级模式
[when(condition)]                           --条件
pl/sql_block;                               --pl/sql语句(begin...end)

四,案例

所需脚本

--创建学生信息表
create table stuInfo
(
  stuNo varchar2(8) not null primary key,
  stuName varchar2(10) not null,
  stuSex varchar2(2) not null,
  stuAge number(6) not null,
  stuSeat number(6) not null,
  strAddress varchar2(255) default('地址不详')
)
 
go
 
--创建学生成绩表
create table stuMarks
(
  ExamNo varchar2(7) not null primary key,
  stuNo varchar2(6) not null references stuInfo(stuNo),
  writtenExam number(6) null,
  LabExam number(6) null
)
 
go
 
--往学生信息表内插入测试数据
insert into stuInfo(stuNo, stuName, stuSex, stuAge,stuSeat,strAddress)
select 's25301', '张秋丽', '男', 18,1, '北京海淀' from dual union
select 's25303', '李斯文', '女', 22,2, '河阳洛阳' from dual union
select 's25302', '李文才', '男', 85, 3,'地址不详' from dual union
select 's25304', '欧阳俊雄', '男', 28, 4,'新疆' from dual union
select 's25318', '梅超风', '女', 23, 5,'地址不详' from dual
 
go
 
--往学生成绩表内插入测试数据
insert into stuMarks(ExamNo, stuNo, writtenExam, LabExam)
select 's271811', 's25303', 93, 59 from dual union
select 's271813', 's25302', 63, 91 from dual union
select 's271816', 's25301', 90, 83 from dual union
select 's271817', 's25318', 63, 53 from dual
 
go
 
select * from stuinfo;
select * from stumarks;

要求李斯文不能删除

1.要求李斯文不能删
create or replace trigger ta
after delete --执行删除后触发
on stuinfo --触发器所在的表
for each row --行级
begin
  --可执行部分
  if(:old.stuname='李斯文') then
    raise_application_error(-20001,'李斯文不能删除');
  end if;
end;
 
--验证
delete from stuinfo where stuname='李斯文'
--核对
select * from stuinfo;

张三不能增加

create or replace trigger tb
after insert
on stuinfo
for each row
begin
  if(:new.stuname='张三') then
    raise_application_error(-20002,'张三不能增加');
  end if;
end;
 
--验证
insert into stuinfo(stuno,stuname,stusex,stuage,stuseat,straddress)
values('s25339','张三','女',38,38,'西班牙')
 
--核实
select * from stuinfo;

李斯文不能修改

create or replace trigger tc
after update
on stuinfo
for each row
begin
  if(:old.stuname='李斯文') then
    raise_application_error(-20003,'李斯文不能修改');
  end if;
end;
 
--验证
update stuinfo set stuname='羊癫疯' where stuname='李斯文'
 
--核实
select * from stuinfo;

合三为一(把上面的触发器合成一个触发器)

create or replace trigger td
after insert or delete or update
on stuinfo
for each row
begin
  case
    when inserting then --当正在执行增加操作的时候
      if(:new.stuname='张三') then
        raise_application_error(-20002,'张三不能加');
      end if;
    when deleting then  --当正在执行删除操作的时候
      if(:old.stuname='李斯文') then
        raise_application_error(-20001,'李斯文不能删');
      end if;
    when updating then  --当正在执行修改操作的时候
      if(:old.stuname='李斯文') then
        raise_application_error(-20003,'李斯文不能改');
      end if;
  end case;
end;

级联删除(删除李斯文的同时成绩自动删除)

create or replace trigger ta
after delete
on stuinfo
for each row
declare
sno varchar2(6);--装李斯文的学号
begin
  if(:old.stuname='李斯文') then
    sno := :old.stuno;--给sno赋值
    delete from stumarks where stuno=sno;--把李斯文对应的成绩删除
  end if;
end;
 
--验证
delete from stuinfo where stuname='李斯文'
--核实
select * from stuinfo;
select * from stumarks;

标识列:序列+触发器

--序列
create sequence seq_0220;
--表:tb_0220(sid,sname,ssex)
create table tb_0220 (
       sid number primary key,
       sname varchar2(20) not null,
       ssex varchar2(10) check(ssex='男' or ssex='女')
)
--触发器:前触发
create or replace trigger tri
before insert --注意:前触发
on tb_0220
for each row
begin
  :new.sid := seq_0220.nextval;--增加之前拿到序列的下一个值给临时表的学号赋值
end;
 
--验证
insert into tb_0220(sname,ssex)
values('王校长','女')
 
--核实
select * from tb_0220
oracle触发器实例讲解2008-11-27 09:17--[6]// Oracle Trigger ---------------------------------------------------------------------------------------------// --实例1------------------------ --创建触发器,当用户对test表执行DML语句时,将相关信息记录到日志表 --创建测试表 CREATE TABLE test ( t_id NUMBER(4), t_name VARCHAR2(20), t_age NUMBER(2), t_sex CHAR ); --创建记录测试表 CREATE TABLE test_log ( l_user VARCHAR2(15), l_type VARCHAR2(15), l_date VARCHAR2(30) ); --创建触发器 CREATE OR REPLACE TRIGGER test_trigger AFTER DELETE OR INSERT OR UPDATE ON test DECLARE v_type test_log.l_type%TYPE; BEGIN IF INSERTING THEN --INSERT触发 v_type := 'INSERT'; DBMS_OUTPUT.PUT_LINE('记录已经成功插入,并已记录到日志'); ELSIF UPDATING THEN --UPDATE触发 v_type := 'UPDATE'; DBMS_OUTPUT.PUT_LINE('记录已经成功更新,并已记录到日志'); ELSIF DELETING THEN v_type := 'DELETE'; DBMS_OUTPUT.PUT_LINE('记录已经成功删除,并已记录到日志'); END IF; INSERT INTO test_log VALUES(user,v_type, TO_CHAR(sysdate,'yyyy-mm-dd hh24:mi:ss')); END; / --下面我们来分别执行DML语句 INSERT INTO test VALUES(101,'zhao',22,'M'); UPDATE test SET t_age = 30 WHERE t_id = 101; DELETE test WHERE t_id = 101; --然后查看效果 SELECT * FROM test; SELECT * FROM test_log; --实例2------------------------ --创建触发器,它将映射emp表中每个部门的总人数和总工资 --创建映射表 CREATE TABLE dept_sal AS SELECT deptno,COUNT(empno) AS total_emp,SUM(sal) AS total_sal FROM emp GROUP BY deptno; DESC dept_sal; --创建触发器 CREATE OR REPLACE TRIGGER emp_info AFTER INSERT OR UPDATE OR DELETE ON emp DECLARE CURSOR cur_emp IS SELECT deptno,COUNT(empno) AS total_emp,SUM(sal) AS total_sal FROM emp GROUP BY deptno; BEGIN DELETE dept_sal; --触发时首先删除映射表信息 FOR v_emp IN cur_emp LOOP --DBMS_OUTPUT.PUT_LINE(v_emp.deptno || v_emp.total_emp || v_emp.total_sal); --插入数据 INSERT INTO dept_sal VALUES(v_emp.deptno,v_emp.total_emp,v_emp.total_sal); END LOOP; END; / --对emp表进行DML操作 INSERT INTO emp(empno,deptno,sal) VALUES('123','10',10000); SELECT * FROM dept_sal; DELETE EMP WHERE empno=123; SELECT * FROM dept_sal; --实例3------------------------ --创建触发器,它记录表的删除数据 --创建表 CREATE TABLE employee ( id VARCHAR2(4) NOT NULL, name VARCHAR2(15) NOT NULL, age NUMBER(2) NOT NULL, sex CHAR NOT NULL ); DESC employee; --插入数据 INSERT INTO employee VALUES('e101','zhao',23,'M'); INSERT INTO employee VALUES('e102','jian',21,'F'); --创建记录表 CREATE TABLE old_employee AS SELECT * FROM employee; DESC old_employee; --创建触发器 CREATE OR REPLACE TRIGGER tig_old_emp AFTER DELETE ON employee -- FOR EACH ROW --语句级触发,即每一行触发一次 BEGIN INSERT INTO old_employee VALUES(:old.id,:old.name,:old.age,:old.sex); --:old代表旧值 END; / --下面进行测试 DELETE employee; SELECT * FROM old_employee; --实例4------------------------ --创建触发器,利用视图插入数据 --创建表 CREATE TABLE tab1 (tid NUMBER(4) PRIMARY KEY,tname VARCHAR2(20),tage NUMBER(2)); CREATE TABLE tab2 (tid NUMBER(4),ttel VARCHAR2(15),tadr VARCHAR2(30)); --插入数据 INSERT INTO tab1 VALUES(101,'zhao',22); INSERT INTO tab1 VALUES(102,'yang',20); INSERT INTO tab2 VALUES(101,'13761512841','AnHuiSuZhou'); INSERT INTO tab2 VALUES(102,'13563258514','AnHuiSuZhou'); --创建视图连接两张表 CREATE VIEW tab_view AS SELECT tab1.tid,tname,ttel,tadr FROM tab1,tab2 WHERE tab1.tid = tab2.tid; --创建触发器 CREATE OR REPLACE TRIGGER tab_trigger INSTEAD OF INSERT ON tab_view BEGIN INSERT INTO tab1(tid,tname) VALUES(:new.tid,:new.tname); INSERT INTO tab2(ttel,tadr) VALUES(:new.ttel,:new.tadr); END; / --现在就可以利用视图插入数据 INSERT INTO tab_view VALUES(105,'zhaoyang','13886681288','beijing'); --查看效果 SELECT * FROM tab_view; --实例5------------------------ --创建触发器,比较emp表中更新的工资 CREATE OR REPLACE TRIGGER sal_emp BEFORE UPDATE ON emp FOR EACH ROW BEGIN IF :OLD.sal > :NEW.sal THEN DBMS_OUTPUT.PUT_LINE('工资减少'); ELSIF :OLD.sal < :NEW.sal THEN DBMS_OUTPUT.PUT_LINE('工资增加'); ELSE DBMS_OUTPUT.PUT_LINE('工资未作任何变动'); END IF; DBMS_OUTPUT.PUT_LINE('更新前工资 :' || :OLD.sal); DBMS_OUTPUT.PUT_LINE('更新后工资 :' || :NEW.sal); END; / --执行UPDATE查看效果 UPDATE emp SET sal = 3000 WHERE empno = '7788'; --实例6------------------------ --创建触发器,将操作CREATE、DROP存储在log_info表 --创建表 CREATE TABLE log_info ( manager_user VARCHAR2(15), manager_date VARCHAR2(15), manager_type VARCHAR2(15), obj_name VARCHAR2(15), obj_type VARCHAR2(15) ); --创建触发器 CREATE OR REPLACE TRIGGER trig_log_info AFTER CREATE OR DROP ON SCHEMA BEGIN INSERT INTO log_info VALUES(USER,SYSDATE,SYS.DICTIONARY_OBJ_NAME,SYS.DICTIONARY_OBJ_OWNER, SYS.DICTIONARY_OBJ_TYPE); END; / --测试语句 CREATE TABLE a(id NUMBER); CREATE TYPE aa AS OBJECT(id NUMBER); / DROP TABLE a; DROP TYPE aa; --查看效果 SELECT * FROM log_info; --相关数据字典-----------------------------------------------------// SELECT * FROM USER_TRIGGERS; SELECT * FROM ALL_TRIGGERS; SELECT * FROM DBA_TRIGGERS; --必须以DBA身份登陆才能使用此数据字典 --启用和禁用 ALTER TRIGGER trigger_name DISABLE; ALTER TRIGGER trigger_name ENABLE;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值