二十九、oracle 触发器

一、触发器简介

触发器的定义就是说某个条件成立的时候,触发器里面所定义的语句就会被自动的执行。因此触发器不需要人为的去调用,也不能调用。然后,触发器的触发条件其实在你定义的时候就已经设定好了。这里面需要说明一下,触发器可以分为语句级触发器和行级触发器。详细的介绍可以参考网上的资料,简单的说就是语句级的触发器可以在某些语句执行前或执行后被触发。而行级触发器则是在定义的了触发的表中的行数据改变时就会被触发一次。
具体举例:
1、 在一个表中定义的语句级的触发器,当这个表被删除时,程序就会自动执行触发器里面定义的操作过程。这个就是删除表的操作就是触发器执行的条件了。
2、 在一个表中定义了行级的触发器,那当这个表中一行数据发生变化的时候,比如删除了一行记录,那触发器也会被自动执行了。

二、触发器语法

触发器的语法:
create [or replace] tigger 触发器名 触发时间 触发事件
on 表名
[for each row]
begin
  pl/sql语句
end
其中:
触发器名:触发器对象的名称。由于触发器是数据库自动执行的,因此该名称只是一个名称,没有实质的用途。
触发时间:指明触发器何时执行,该值可取:
before:表示在数据库动作之前触发器执行;
after:表示在数据库动作之后触发器执行。
触发事件:指明哪些数据库动作会触发此触发器:
insert:数据库插入会触发此触发器;
update:数据库修改会触发此触发器;
delete:数据库删除会触发此触发器。
表 名:数据库触发器所在的表。
for each row:对表的每一行触发器执行一次。如果没有这一选项,则只对整个表执行一次。

触发器能实现如下功能:

功能:
1、 允许/限制对表的修改
2、 自动生成派生列,比如自增字段
3、 强制数据一致性
4、 提供审计和日志记录
5、 防止无效的事务处理
6、 启用复杂的业务逻辑

举例
1)、下面的触发器在更新表tb_emp之前触发,目的是不允许在周末修改表:

create or replace trigger auth_secure before insert or update or DELETE on tb_empbegin   IF(to_char(sysdate,‘DY‘)=‘星期日‘) THEN       RAISE_APPLICATION_ERROR(-20600,‘不能在周末修改表tb_emp‘);   END IF;END;/

2)、使用触发器实现序号自增
创建一个测试表:

create table tab_user(   id number(11) primary key,   username varchar(50),   password varchar(50));

创建一个序列:

create sequence my_seq increment by 1 start with 1 nomaxvalue nocycle cache 20;

创建一个触发器:

CREATE OR REPLACE TRIGGER MY_TGR  BEFORE INSERT ON TAB_USER  FOR EACH ROW--对表的每一行触发器执行一次DECLARE  NEXT_ID NUMBER;BEGIN  SELECT MY_SEQ.NEXTVAL INTO NEXT_ID FROM DUAL;  :NEW.ID := NEXT_ID; --:NEW表示新插入的那条记录END;

向表插入数据:

insert into tab_user(username,password) values(‘admin‘,‘admin‘);insert into tab_user(username,password) values(‘fgz‘,‘fgz‘);insert into tab_user(username,password) values(‘test‘,‘test‘);COMMIT;

查询表结果:SELECT * FROM TAB_USER;

3)、当用户对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 TESTDECLARE  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    --DELETE触发    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‘)); --USER表示当前用户名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;

运行结果如下:

3)、创建触发器,它将映射emp表中每个部门的总人数和总工资

--创建映射表CREATE TABLE dept_sal AS SELECT deptno, COUNT(empno) total_emp, SUM(sal) total_sal FROM scott.emp GROUP BY deptno;

--创建触发器CREATE OR REPLACE TRIGGER EMP_INFO  AFTER INSERT OR UPDATE OR DELETE ON scott.EMPDECLARE  CURSOR CUR_EMP IS    SELECT DEPTNO, COUNT(EMPNO) AS TOTAL_EMP, SUM(SAL) AS TOTAL_SAL FROM scott.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;

显示结果如下:

4)、创建触发器,用来记录表的删除数据

--创建表CREATE TABLE employee(   id   VARCHAR2(4)  NOT NULL,    name VARCHAR2(15) NOT NULL,    age  NUMBER(2)    NOT NULL,    sex  CHAR NOT NULL);

--插入数据INSERT INTO employee VALUES(‘e101‘,‘zhao‘,23,‘M‘);INSERT INTO employee VALUES(‘e102‘,‘jian‘,21,‘F‘);

--创建记录表(包含数据记录)CREATE TABLE old_employee AS SELECT * FROM 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;

5)、创建触发器,利用视图插入数据

--创建表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 OR REPLACE 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_VIEWBEGIN  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(106,‘ljq‘,‘13886681288‘,‘beijing‘);

--查询SELECT * FROM tab_view;SELECT * FROM tab1;SELECT * FROM tab2;

6)、创建触发器,比较emp表中更新的工资

--创建触发器set serveroutput on;CREATE OR REPLACE TRIGGER SAL_EMP  BEFORE UPDATE ON EMP  FOR EACH ROWBEGIN  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‘;

运行结果如下:

7)、创建触发器,将操作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));

--创建触发器set serveroutput on;CREATE OR REPLACE TRIGGER TRIG_LOG_INFO  AFTER CREATE OR DROP ON SCHEMABEGIN  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;
--必须以DBA身份登陆才能使用此数据字典
SELECT * FROM ALL_TRIGGERS;SELECT * FROM DBA_TRIGGERS;

--启用和禁用
ALTER TRIGGER trigger_name DISABLE;
ALTER TRIGGER trigger_name ENABLE;

--------------------------------------------------

时间: 2024-08-08 00:54:03

二十九、oracle 触发器的相关文章

攻城狮在路上(叁)Linux(二十九)--- 完整备份工具:dump以及restore

一.dump命令: 该命令既可以针对整个文件系统进行备份,也可以仅针对目录来备份.还可以指定不同的备份等级(-0~-9共10个等级). dump -W:列出在/etc/fstab中具有dump设置的分区是否备份过. 命令格式: dump [-Suvj] [-level] [-f 备份文件] 待备份数据 参数说明: -S:仅列出后面的待备份数据所需要的磁盘空间大小. -u:将这次dump的时间记录到/etc/dumpdates文件中. -v:将dump的文件过程显示出来. -j:加入bzip2的支

企业搜索引擎开发之连接器connector(二十九)

在哪里调用监控器管理对象snapshotRepositoryMonitorManager的start方法及stop方法,然后又在哪里调用CheckpointAndChangeQueue对象的resume方法获取List<CheckpointAndChange> guaranteedChanges集合 下面跟踪到DiffingConnectorTraversalManager类的相关方法,在该类实现的方法中,调用了监控器管理对象snapshotRepositoryMonitorManager的相

Android学习笔记二十九之SwipeRefreshLayout、RecyclerView和CardView

Android学习笔记二十九之SwipeRefreshLayout.RecyclerView和CardView 前面我们介绍了AlertDialog和几个常用的Dialog,ProgressDialog进度条提示框.DatePickerDialog日期选择对话框和TimePickerDialog时间选择对话框.这一节我们介绍几个新的API控件SwipeRefreshLayout.RecyclerView和CardView,这几个API控件都是google在Android5.0推出的.下面我们来学

[原创]ActionScript3游戏中的图像编程(连载二十九)

2.2.2 Photoshop投影大小的模拟 投影没有之前那么浓了,但是跟Photoshop里的效果差别还挺大,因为在Photoshop里我们还设置了另外一个属性:大小. Flash里似乎找不到它的影子,我们用排除法来进行定位,Photoshop投影样式的大小属性以像素为单位,Flash投影滤镜的选项只有距离和那对被“手铐”扣住的模糊属性符合条件,而Photoshop里也有一个距离,所以我们定位到模糊属性(图 2.15). 图 2.15 Flash投影的模糊属性 分别调整Photoshop的大小

Welcome to Swift (苹果官方Swift文档初译与注解二十九)---209~218页(第四章-- 流程控制)

Break break语句会立刻结束整个流程控制的执行.break语句可以在switch语句或者循环语句中帮助你提前结束循环或者switch的执行. Break in a Loop Statement  (循环语句中的break) 当在循环语句中使用break,会立刻结束循环的执行,并且跳转到循环体之后的第一行代码.循环不会再遍历执行了. Break in a Switch Statement (switch语句的break) 当在switch语句中使用break,break会立刻结速switc

每日算法之二十九:Search in Rotated Sorted Array

在一个经过旋转后的有序数组中查找一个目标元素. Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). You are given a target value to search. If found in the array return its index, otherwise return -1.

ActionScript3游戏中的图像编程(连载二十九)

2.2.2 Photoshop投影大小的模拟 投影没有之前那么浓了,但是跟Photoshop里的效果差别还挺大,因为在Photoshop里我们还设置了另外一个属性:大小. Flash里似乎找不到它的影子,我们用排除法来进行定位,Photoshop投影样式的大小属性以像素为单位,Flash投影滤镜的选项只有距离和那对被"手铐"扣住的模糊属性符合条件,而Photoshop里也有一个距离,所以我们定位到模糊属性(图 2.15). 图 2.15 Flash投影的模糊属性 分别调整Photosh

【Unity 3D】学习笔记二十九:游戏实例——简单小地图制作

任何的学习,光看不练是学不好的.所以这次就总结回顾下怎么制作MMROPG类游戏中的小地图.在MMROPG类游戏里,主角在游戏世界里走动时,一般在屏幕右上角都会有一个区域来显示当前游戏场景的小地图.主角在游戏世界里走动,小地图里代表着主角的小标记也会随之移动.那怎么实现咧? 首先需要确定两个贴图,第一个是右上角的小地图背景贴图,应该是从Y轴俯视向下截取主角所在的位置大地图.第二个就是主角的位置大贴图.在本例中,因为没有学习unity地图制作,所以地图用一个面对象代替,主角用立方体代替,使用GUI来

二十九、linux常用命令(一)

vim是打开vim编辑器,别的编辑器还有vi(功能没有vim 强大),nano,emacs等等,感觉还是vim最强大,其次是vi,别的就要差一些了. 我听我们老师说,用图形界面本身已经会被高手笑了,如果打开一个gpedit或者kwrite那就废了......常用的命令 ls,列出当前目录下的文件,ls -l是列出详细信息,ls -a列出隐藏文件. cd,更改目录.clear,清屏命令.reset,重置终端. startx,启动图形界面.fdisk -l,查看硬盘分区. ps aux,列出系统进程

29、蛤蟆的数据结构笔记之二十九数组之硬币抛掷模拟

29.蛤蟆的数据结构笔记之二十九数组之硬币抛掷模拟 本篇名言:"人生是各种不同的变故.循环不已的痛苦和欢乐组成的.那种永远不变的蓝天只存在于心灵中间,向现实的人生去要求未免是奢望.-- 巴尔扎克" 欢迎转载,转载请标明出处: 1.  硬币抛掷 如果抛掷硬币N次,看到头像的期望值是N/2次,但实际值也可能是0~N次,在程序中进行M次试验,M和N都在代码中定义.它使用一个数组f来跟踪出现"i次头像"的概率,其中0≤j≤N.然后打印试验结果的柱状图,每出现10次用1个星号