Oracle触发器用法实例详解

本文实例讲述了Oracle触发器用法。分享给大家供大家参考,具体如下:

一、触发器简介

触发器的定义就是说某个条件成立的时候,触发器里面所定义的语句就会被自动的执行。

因此触发器不需要人为的去调用,也不能调用。

然后,触发器的触发条件其实在你定义的时候就已经设定好了。

这里面需要说明一下,触发器可以分为语句级触发器和行级触发器。

详细的介绍可以参考网上的资料,简单的说就是语句级的触发器可以在某些语句执行前或执行后被触发。而行级触发器则是在定义的了触发的表中的行数据改变时就会被触发一次。

具体举例:

1、 在一个表中定义的语句级的触发器,当这个表被删除时,程序就会自动执行触发器里面定义的操作过程。这个就是删除表的操作就是触发器执行的条件了。
2、 在一个表中定义了行级的触发器,那当这个表中一行数据发生变化的时候,比如删除了一行记录,那触发器也会被自动执行了。

二、触发器语法

触发器的语法:

1
2
3
4
5
6
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之前触发,目的是不允许在周末修改表:

1
2
3
4
5
6
7
8
create or replace trigger auth_secure before insert or update or DELETE
on tb_emp
begin
IF(to_char(sysdate,‘DY‘)=‘星期日‘) THEN
RAISE_APPLICATION_ERROR(-20600,‘不能在周末修改表tb_emp‘);
END IF;
END;
/
2)、使用触发器实现序号自增

创建一个测试表:

1
2
3
4
5
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;
创建一个触发器:

1
2
3
4
5
6
7
8
9
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;
向表插入数据:

1
2
3
4
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语句时,将相关信息记录到日志表

1
2
3
4
5
6
7
8
9
10
11
12
13
--创建测试表
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)
);
创建触发器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
--创建触发器
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
--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表中每个部门的总人数和总工资

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
--创建映射表
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.EMP
DECLARE
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)、创建触发器,用来记录表的删除数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
--创建表
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)、创建触发器,利用视图插入数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
--创建表
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_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(106,‘ljq‘,‘13886681288‘,‘beijing‘);
--查询
SELECT * FROM tab_view;
SELECT * FROM tab1;
SELECT * FROM tab2;
6)、创建触发器,比较emp表中更新的工资

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
--创建触发器
set serveroutput on;
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‘;
运行结果如下:

7)、创建触发器,将操作CREATE、DROP存储在log_info表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
--创建表
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 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;
--必须以DBA身份登陆才能使用此数据字典
SELECT * FROM ALL_TRIGGERS;SELECT * FROM DBA_TRIGGERS;
--启用和禁用
ALTER TRIGGER trigger_name DISABLE;
ALTER TRIGGER trigger_name ENABLE;
希望本文所述对大家Oracle数据库程序设计有所帮助。

原文地址:https://www.cnblogs.com/meijiemu/p/9073183.html

时间: 2024-10-12 11:14:32

Oracle触发器用法实例详解的相关文章

PHP中__get()和__set()的用法实例详解

PHP中__get()和__set()的用法实例详解 在PHP5中,预定义了两个函数“__get()”和“__set()”来获取和赋值其属性,对每个字段进行set和get的操作.只需要加上两个魔术方法即可 php面向对象_get(),_set()的用法 一般来说,总是把类的属性定义为private,这更符合 现实的逻辑.但是,对属性的读取和赋值操作是非常频繁的,因此在PHP5中,预定义了两个函数“__get()”和“__set()”来获取和赋值其属 性.类似于java中的javabean的操作,

C#中string用法实例详解

在进行C#程序设计时,用的最多的莫过于string了,但有些时候由于不仔细或者基础的不牢固等因素容易出错,今天本文就来较为详细的总结一下C#中string的用法.具体如下: 1.string是一个引用类型,平时我们比较string对象,比较的是对象的值而不是对象本身 如下面代码所示: string strA="abcde"; string strB="abc"; string strC="de"; Console.WriteLine(strA =

C#泛型Dictionary的用法实例详解

本文以实例形式讲述了C#中的泛型Dictionary的用法.具有很好的实用价值.分享给大家供大家参考.具体如下: 泛型最常见的用途是泛型集合,命名空间System.Collections.Generic 中包含了一些基于泛型的集合类,使用泛型集合类可以提供更高的类型安全性,还有更高的性能,避免了非泛型集合的重复的装箱和拆箱. 很多非泛型集合类都有对应的泛型集合类,下面是常用的非泛型集合类以及对应的泛型集合类: 非泛型集合类 泛型集合类 ArrayList List<T> HashTable D

C#的FileSystemWatcher用法实例详解

本文实例详述了C#的FileSystemWatcher用法.分享给大家供大家参考.具体用法如下: FileSystemWatcher控件主要功能: 监控指定文件或目录的文件的创建.删除.改动.重命名等活动.可以动态地定义需要监控的文件类型及文件属性改动的类型. 1.常用的几个基本属性: (1) Path :设置要监视的目录的路径. (2) IncludeSubdirectories :设置是否级联监视指定路径中的子目录. (3) Filter :设置筛选字符串,用于确定在目录中监视哪些类型的文件

ORACLE触发器基础技术详解

ORACLE PL/SQL编程之八: 把触发器说透 本篇主要内容如下: 8.1 触发器类型 8.1.1 DML触发器 8.1.2 替代触发器 8.1.3 系统触发器 8.2 创建触发器 8.2.1 触发器触发次序 8.2.2 创建DML触发器 8.2.3 创建替代(INSTEAD OF)触发器 8.2.3 创建系统事件触发器 8.2.4 系统触发器事件属性 8.2.5 使用触发器谓词 8.2.6 重新编译触发器 8.3 删除和使能触发器 8.4 触发器和数据字典 8.5   数据库触发器的应用举

Python多进程并发(multiprocessing)用法实例详解

http://www.jb51.net/article/67116.htm 本文实例讲述了Python多进程并发(multiprocessing)用法.分享给大家供大家参考.具体分析如下: 由于Python设计的限制(我说的是咱们常用的CPython).最多只能用满1个CPU核心.Python提供了非常好用的多进程包multiprocessing,你只需要定义一个函数,Python会替你完成其他所有事情.借助这个包,可以轻松完成从单进程到并发执行的转换. 1.新建单一进程 如果我们新建少量进程,

js确认框confirm()用法实例详解

先为大家介绍javascript确认框的三种使用方法,具体内容如下 第一种方法:挺好用的,确认以后才能打开下载地址页面.原理也比较清晰.主要用于删除单条信息确认. ? 1 2 3 4 5 6 7 8 9 10 <SCRIPT LANGUAGE=javascript> function del() {  var msg = "您真的确定要删除吗?\n\n请确认!";  if (confirm(msg)==true){   return true;  }else{   retu

jquery中cookie用法实例详解(获取,存储,删除等)

这篇文章主要介绍了jquery中cookie用法,结合实例详细分析了jQuery操作cookie的获取,存储,删除等操作,并附带了Jquery操作Cookie记录用户查询过信息实现方法,需要的朋友可以参考下 本文实例讲述了jquery中cookie用法.分享给大家供大家参考,具体如下: cookie在jquery中有指定的cookie操作类,下面我先来介绍我们在使用cookie操作类时的一些问题,然后介绍正确的使用方法. 使用JQuery操作cookie时 发生取的值不正确的问题: 结果发现co

Python回调函数用法实例详解

本文实例讲述了Python回调函数用法.分享给大家供大家参考.具体分析如下: 一.百度百科上对回调函数的解释: 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应. 二.什么是回调: 软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用.回调和异步调用.同步调用