from:http://blog.csdn.net/zhanzhib/article/details/48729417

触发器的意思就是当我们对数据库对象(一般是表或视图)进行insert、update、delete操作的时候,这些操作会相应的触发一些事件的执行,通常要执行的事件被写成PL/SQL程序,那么这些数据库对象上的事件相关的程序就是触发器(trigger)。Oracle数据库中,触发器分为before、after、instead of三种,其中before、after主要对于表操作,instead of主要对于视图操作,因为如果视图是多表的时候,不能直接进行DML操作,这个时候可以建立代替触发器(instead of)来替换事件本身的动作。同时,触发器也可以分为row级和statement级两种,row级的触发器在每次DML一行时执行,statement触发器一个SQL语句引发一次,不管影响几行。

图1:trigger的触发顺序

上图1非常重要,对于trigger的触发顺序的解释一目了然,尤其是下半副图,update数据的时候,对于statement trigger,不管是before还是after,都只会执行一次,而row trigger,却会在每次的udpate的前后执行一次。

1、before、after触发器

创建statement trigger和row trigger的语法直接看下面代码:

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
-- statement级before trigger
CREATE OR REPLACE TRIGGER secure_emp
  BEFORE INSERT OR DELETE OR UPDATE ON employees
BEGIN
  IF (TO_CHAR(SYSDATE, 'DY'IN ('SAT''SUN')) OR
     (TO_CHAR(SYSDATE, 'HH24:MI'NOT BETWEEN '08:00' AND '18:00'THEN
    RAISE_APPLICATION_ERROR(-20500,
                            'You may modify EMPLOYEES table only on weekdays.');
  END IF;
END;
-- row级before trigger
CREATE OR REPLACE TRIGGER restrict_salary
  BEFORE INSERT OR UPDATE OF salary ON employees
  FOR EACH ROW
BEGIN
  IF NOT (:NEW.job_id IN ('AD_PRES''AD_VP')) AND :NEW.salary > 15000 THEN
    RAISE_APPLICATION_ERROR(-20202, 'Error');
  END IF;
END;
-- row级after trigger,注意:new和:old的用法
CREATE OR REPLACE TRIGGER audit_emp_values
  AFTER DELETE OR INSERT OR UPDATE ON employees
  FOR EACH ROW
BEGIN
  INSERT INTO audit_emp_table
    (user_name,
     TIMESTAMP,
     id,
     old_last_name,
     new_last_name,
     old_title,
     new_title,
     old_salary,
     new_salary)
  VALUES
    (USER,
     SYSDATE,
     :OLD.employee_id,
     :OLD.last_name,
     :NEW.last_name,
     :OLD.job_id,
     :NEW.job_id,
     :OLD.salary,
     :NEW.salary);
END;
-- row级before trigger,注意when的用法
CREATE OR REPLACE TRIGGER derive_commission_pct
  BEFORE INSERT OR UPDATE OF salary ON employees
  FOR EACH ROW
  WHEN (NEW.job_id = 'SA_REP')
BEGIN
  IF INSERTING THEN
    :NEW.commission_pct := 0;
  ELSIF :OLD.commission_pct IS NULL THEN
    :NEW.commission_pct := 0;
  ELSE
    :NEW.commission_pct := :OLD.commission_pct + 0.05;
  END IF;
END;

对于:OLD和:NEW的用法,需要注意的是它们什么时候存在什么时候可用,:old表示引用以前的列值,:new表示引用最新的列值,这两个变量都只能在for each row存在的时候才可用,且update语句:old和:new都有,delete语句只有:old,insert语句只有:new。

2、instead of触发器

对于instead of触发器,一般都是用在复杂视图上,用于对复杂视图中相关表的更新操作。如下例所示(代码收录自网络):

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
37
38
39
40
41
42
43
44
45
46
47
48
-- 创建表
CREATE TABLE STUDENT
(
   CODE  VARCHAR2(5),
   LNAME VARCHAR2(200)
)
CREATE TABLE COURSE
(
    CODE  VARCHAR2(5),
    CNAME VARCHAR2(30)
)
CREATE TABLE ST_CR
(
   STUDENT VARCHAR2(5),
   COURSE  VARCHAR2(5),
   GRADE   NUMBER
)
-- 表的约束
ALTER TABLE STUDENT ADD CONSTRAINT STUDENT$PK PRIMARY KEY(CODE);
ALTER TABLE COURSE ADD CONSTRAINT COURSE$PK PRIMARY KEY(CODE);
ALTER TABLE ST_CR ADD CONSTRAINT ST_CR$PK PRIMARY KEY(STUDENT, COURSE);
ALTER TABLE ST_CR ADD CONSTRAINT ST_CR$FK$STUDENT FOREIGN KEY(STUDENT) REFERENCES STUDENT(CODE);
ALTER TABLE ST_CR ADD CONSTRAINT ST_CR$FK$COURSE FOREIGN KEY(COURSE) REFERENCES COURSE(CODE);
-- 创建基于这三个表的视图
CREATE OR REPLACE VIEW STUDENT_STATUS AS
   SELECT S.CODE S_CODE, S.LNAME STUDENT, C.CODE C_CODE, C.CNAME COURSE, SC.GRADE GRADE
      FROM STUDENT S, COURSE C, ST_CR SC
        WHERE S.CODE = SC.STUDENT
          AND C.CODE = SC.COURSE
-- 创建基于视图的instead of触发器
CREATE OR REPLACE TRIGGER TRI_STCR INSTEAD OF INSERT ON STUDENT_STATUS
   FOR EACH ROW
DECLARE
  W_ACTION VARCHAR2(1);
BEGIN
  IF    INSERTING THEN
    W_ACTION := 'I';
  ELSE
    RAISE PROGRAM_ERROR;
  END IF;
    INSERT INTO STUDENT(CODE, LNAME) VALUES(:NEW.S_CODE,:NEW.STUDENT);
    INSERT INTO COURSE(CODE, CNAME) VALUES(:NEW.C_CODE, :NEW.COURSE);
    INSERT INTO ST_CR(STUDENT, COURSE, GRADE)
       VALUES(:NEW.S_CODE, :NEW.C_CODE, :NEW.GRADE);
END;
-- 对视图执行数据插入,如果这里没有建过instead of触发器,很明显对复杂视图进行DML操作是会出错的
INSERT INTO STUDENT_STATUS(S_CODE, STUDENT, C_CODE, COURSE, GRADE)
       VALUES('001','Mike','EN','English',86);

3、管理Trigger

1
2
3
4
ALTER TRIGGER trigger_name DISABLE; -- 失效,生效改为enable
ALTER TABLE table_name DISABLE ALL TRIGGERS; -- 批量失效,批量生效改为enable
ALTER TRIGGER trigger_name COMPILE; -- 重新编译trigger
DROP TRIGGER trigger_name; -- 删除trigger

oracle数据库中trigger的使用,大概就是这样,虽然看着比较多,但是在实际中确是不太建议使用的,因为维护起来很不方便,所以在能不用trigger的地方还是不用为好。

2015年01月16日补充:

oracle对触发器提供了如下的一些谓词:

(1)inserting:当触发事件是insert时,取值为true,否则为false。

(2)updating[(column_1, column_2, ..., column_x)]:当触发事件是update时,如果修改了column_x列,则取值为true,否则为false。其中,column_x是可选的。

(3)deleting:当触发事件是delete时,则取值为true,否则为false。

 

oracle数据库触发器(trigger)用法总结的更多相关文章

  1. Oracle数据库——触发器的创建与应用

    一.涉及内容 1.理解触发器的概念.作用和类型. 2.练习触发器的创建和使用. 二.具体操作 (实验) 1.利用触发器对在scott.emp表上执行的DML操作进行安全性检查,只有scott用户登录数 ...

  2. Oracle数据库触发器使用(删除触发)

    当我们需要用到触发器的时候,还是很方便,你会指定当我在操作某一事件时触发效果完成我所希望完成的事情:这就是触发器, 下面我给大家上一串代码,这是一个当我在操作删除事件操作时候,我希望把即将删除那条数据 ...

  3. mysql 触发器 trigger用法 four

    实验4 触发器 (1)实验目的 掌握数据库触发器的设计和使用方法 (2)实验内容和要求 定义BEFORE触发器和AFTER触发器.能够理解不同类型触发器的作用和执行原理,验证触发器的有效性. (3)实 ...

  4. mysql 触发器 trigger用法 two (稍微复杂的)

    触发器(trigger):监视某种情况,并触发某种操作. 触发器创建语法四要素:1.监视地点(table) 2.监视事件(insert/update/delete) 3.触发时间(after/befo ...

  5. mysql 触发器 trigger用法 three (稍微复杂的)

    MySQL包含对触发器的支持.触发器是一种与表操作有关的数据库对象,当触发器所在表上出现指定事件时,将调用该对象,即表的操作事件触发表上的触发器的执行. 创建触发器 在MySQL中,创建触发器语法如下 ...

  6. Oracle数据库---触发器

    SQL> --当我们对empnew执行删除操作之后,它就会出现一个提示信息,提示:这是删除操作!SQL> CREATE TRIGGER first_trigger 2 AFTER DELE ...

  7. oracle 数据库触发器,插入更新时间戳

    1.首先建立一个测试表 CREATE TABLE TestTragger( UserId int Primary Key, Name VARCHAR() Not Null, CreateTime Ti ...

  8. MySQL数据库触发器(trigger)

    MySQL触发器(trigger):监视某种情况并触发某种操作 一:四要素 触发时间:before/after 地点:table 监视操作:insert/update/delete 触发操作:inse ...

  9. mysql 触发器 trigger用法 one (简单的)

    实例~~ example1: 创建表tab1 1 2 3 4 DROP TABLE IF EXISTS tab1; CREATE TABLE tab1(     tab1_id varchar(11) ...

随机推荐

  1. linux命令(31):more

    一.more命令 more功能类似 cat ,cat命令是整个文件的内容从上到下显示在屏幕上. more会以一页一页的显示方便使用者逐页阅读,而最基本的指令就是按空白键(space)就往下一页显示,按 ...

  2. zuul超时及重试配置1

    eureka: client: register-with-eureka: true serviceUrl: defaultZone: http://localhost:8761/eureka/ se ...

  3. servlet的编码原理

    编码问题: 在介绍编码问题前,先介绍一下java平台(JVM)上的编码转化情况.首先要说明的一点,在JVM中,即java平台上,运行的程序一定都是Unicode编码方式的.对于代码中的字符串常量,根据 ...

  4. Python的sys.argv使用说明 通过终端写入环境变量

    刚开始使用这个参数的时候,很不明白其含义.网上搜索很多都是贴的官网上面的一则实例,说看懂,就明白.可是,我看不懂.现在在回头看这个参数使用,并不是很麻烦. 举几个小例子就明白了. 创建一个脚本,内容如 ...

  5. 通过Windows PowerShell远程管理计算机(精简版)

    现在你手中有一台server(主控端),你打算通过主控端远程管理多台server(被控端).这个过程可以通过Windows PowerShell来完成. 首先在被控端上以管理员权限打开PowerShe ...

  6. ORM框架为什么不流行了

    程序员的逻辑是先写sql脚本,然后在编写对应的实体代码. orm框架的逻辑是先写实体代码,然后自动生成脚本,构建数据库,这和程序员的逻辑或习惯刚好相反,所以这类ORM框架渐渐的被淘汰了,例如:Hibe ...

  7. maven-gpg-plugin:1.2:sign (sign-artifacts) on project jdbc-pool: Cannot obtain passphrase in batch mode或者是Plugin execution not covered by lifecycle configuration

    本解决方案转自:http://blog.csdn.net/tangximing123/article/details/21179467 执行 Maven install 时报错: Failed to ...

  8. 【WPF/WAF】设置快捷键(Shortcut Key)

    基于WAF框架:WPF Application Framework (WAF) View层XAML中设置热键. <Window.InputBindings> <!--<KeyB ...

  9. 【Unity/C#】DateTime时间字符串,月份用英文显示

    制作一个钟表,要求效果如下图: 由于每一部分的字体大小不同,我分别使用了不同的Text控件.(不懂dalao们有没有更科学的办法) 把这些Text控件包含在一个Object下,给该Object定义一个 ...

  10. c#利用反射Assembly 对类和成员属性进行操作

    protected static void test() { //获取程序集 Assembly assembly = System.Reflection.Assembly.GetExecutingAs ...