欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据库程序设计8 触发器

程序员文章站 2022-07-13 16:36:56
...

目录

触发器

类型

触发器设计原则

DML触发器

创建

触发事件

语句触发器

行触发器

INSTEAD_OF触发器

维护

删除

数据库触发器和存储过程之间的区别


触发器

  • 是特殊的PL/SQL块或存储过程
  • 是基于表、视图、方案、数据库的
  • 是针对特定事件发生时触发的
  • 是隐式执行的

能够更为复杂的控制用户的操作,例如:周末不允许进行离职手续等。

自动处理一些值,例如:账目低于多少钱自动发消息。

类型

应用程序触发器

在应用程序内发生特定DML事件时,将隐式触发它

数据库触发器

在表、视图、方案或数据库上发生特定事件时,将隐式触发它

触发器设计原则

设计触发器为了:

  • 保证当一个指定的操作被执行时,执行相关的动作
  • 集中全局操作

如果触发器的算法很长,将算法创建于存储过程中,再在触发器中调用它们,触发器的大小不能超过32K。过分地使用触发器可能导致复杂的依赖,这在大的应用程序中可能会产生维护困难。

DML触发器

一个触发器语句包含:
触发时间

  • 对于表: BEFORE, AFTER
  • 对于视图: INSTEAD OF

触发事件: INSERT, UPDATE或DELETE
表名: On table、view
触发器类型: Row或statement (只执行一次)
WHEN子句:限制条件,只能在行级触发器中使用
触发器体: PL/SQL块

部分 说明 可能值
触发器时机 当触发器涉及触发事件时的触发时机 BEFORE、AFTER、INSTEAD OF
触发事件 在表或视图上的哪一-个数据操纵操作引发了触发器触发 INSERT、UPDATE、DELETE
触发器类型 触发器体被执行多少次 Sta tement、ROW
触发器体 触发器执行的那些动作 PL/SQL块

创建

语法:

CREATE [OR REPLACE] TRIGGER
    trigger_name
[ BEFOREI AFTER]
[ INSERTI UPDATE [of column] | DELETE]
ON table name
Trigger_body

例子:

员工信息只有在工作日才能进行修改

CREAT OR REPLACE TRIGGER sal_emp
BEFORE INSERT ON emp
BEGIN
    IF(to_char(sysdate),'DY') in ('星期六','星期日')
    then
        raise_application_error(-20001,'只有工作日才能录入数据');
    END IF
END;

INSERT INTO
    emp(empno,ename,job,mgr,hiredate,sal)
VALUES(1002,'ljs','clerk',7902,sysdate,2000);

触发事件

触发事件可以是表上的INSERT、UPDATE或DELETE语句。

当触发事件是一个UPDATE语句时,可以用一个字段列表来确定那些必需触发触发器自来改变的列。不能为INSERT或DELETE语句指定字段列表,因为它们总是影响整个行(...UPDATE OF sal...)。

对于语句触发器,触发事件对于触发器执行一次;对于行触发器,触发事件仅当行被修改时触发。

例如:

数据库程序设计8 触发器

语句触发器

例子:

create or replace trigger trg_empl_ins
    after insert on empl

begin
    INSERT INTO empl_new (empno, ename,sal)
    VALUES (999, '张三', 3000) ;
end trg_empl_ins;
CREATE TABLE empl_new
AS SELECT *FROM emp
WHERE empno IS
NULL
INSERT INTO empl ( empno, ename, sal)
VALUES (888,'李四',4000)

这样就实现了在两张表同时添加数据了,做成了两张表的同步。一条是insert的一条是触发器添加的。

行触发器

使用关键字for each row

创建语法:

CREATE [OR REPLACE] TRIGGER trigger_ name
[BEFORE | AFTER ]
[ INSERT | UPDATE [of column] | DELETE]
ON table_name
[ REFERENCING OLD as old | NEW as new]
FOR EACH ROW
[WHEN (condition)]
Trigger_body

NEW代表新加的数据,OLD代表老数据。灵活使用,例如删除的时候没有新值,修改时old,new都有。

例子:

CREATE OR REPLACE TRIGGER sal_emp
BEFORE UPDATE OF sal ON emp
FOR EACH ROW
BEGIN
    IF(:new.sal >:old.sa1) THEN
    raise_application_error(-20001,薪水太高了); 
END IF;
END;

UPDATE emp SET sal=5000;

在BEGIN之前不用加冒号,在BEGIN内的语句体内需要加冒号(表示外部变量)

例子:

create or replace trigger trg_emp1_ins_row
    after insert on emp1
    for each row
begin
    INSERT INTO emp_new(empno, ename,sal)
    VALUES ( :NEW. empno, :NEW. ename, :NEW.sal);
end trg_empl_ins_row;

这样也能做成两张相同的表。

注意:回滚时两张表的数据均会回滚掉。COMMIT命令不能出现在触发器中。

INSTEAD_OF触发器

视图上是不能插入数据的,但是如果创建一个instead_of触发器,就可以实现在视图中向表中插入数据。

语法:

CREATE OR REPLACE TRIGGER trigger_name
INSTEAD OF
[INSERT | UPDATE [OF column] | DELETE]
ON view_ ame
[REFERENCING OLD as old | NEW as new]
FOR EACH ROW
Trigger_body

 

维护

ALTER TRIGGER trigger name DISABLE| ENABLE

 例如在提前编好触发器,先禁用掉,等需要的时候上线使用。

删除

DROP TRIGGER trigger_name ;

 另外,当表被删除时,表上的所有触发器都被删除。

数据库触发器和存储过程之间的区别

                             触发器                               过程
用CREATE TRIGGER定 义 用CREATE PROCEDURE定义
在数据字典USER TRIGGERS中包含源代码 在数据字典USER_SOURCE中包含源代码
隐式调用 显式调用
不允许COMMIT,SAVEPOINT和ROLLBACK 允许COMMIT,SAVEPOINT和ROLLBACK


 

相关标签: 数据库 oracle