触发器:
◆ 是一个PL/SQL快或者是与表,试图方案或数据库关联的PL/SQL过程
◆ 当特定的事件发生时隐式执行
触发器可以是:
◆ 应用程序触发器:当特定的应用程序的事件发生时触发
◆ 数据库触发器:当数据事件(DML)在一个方案上发生或系统事件(例如:登录或关闭数据库)在数据库上发生时触发
使用触发器的原则:
◆ 创建存储过程并且在触发器中调用它们,如果PL/SQL 代码非常长。
◆ 过分地使用触发器可能导致复杂的依赖,这在大的应用程序中可能会产生维护困难。
触发器包含:
◆ 触发时间(表:BEFORE,AFTER.试图:INSTEAD OF)
◆ 触发事件(INSERT,UPDATE,DELETE)
◆ 触发类型(ROW,STATEMENT)
◆ 触发器体(PL/SQL块)
数据库触发器:
在写触发器代码之前,确定触发器各部分的值:触发时机、触发事件和触发类型。
部分 说明 可能值
触发器时机
当触发器涉及的触发事件时的触发时机 BEFORE、AFTER 、INSTEAD OF
触发事件 在表或视图上的哪一个数据操纵操作引发了触发器触发 INSERT、UPDATE、DELETE
触发器类型 触发器体被执行多少次 Statement、Row
触发器体 触发器执行的那些动作 PL/SQL 块
如果在一个表上定义了多个触发器,要意识到相同类型的多个触发器的触发顺序是随机的。为了保证相同类型的多个触发器以特定的顺序触发,统一多个触发器到一个触发器中,再以想要的顺序分别调用过程。
• BEFORE:在表上触发DML事件之前执行触发器体。
• AFTER: 在表上触发DML事件之后执行触发器体。
• INSTEAD OF:执行触发器体代替触发语句。用于不能以别的方式修改的视图。
触发器类型:触发器体将对语句影响的每行都执行,还是只执行一次?
语句:触发器体对于触发事件执行一次,这是默认。一个语句触发器触发一次,即使根本没有行受影响。
• 行:触发体对受触发事件影响的每行执行一次。如果触发事件没有受影响的行,行触 发器不执行。
触发器体:触发器将执行的哪些动作?触发器体是一个PL/SQL 块或对一个过程的调用。
• 触发器动作定义那些再触发事件被发布时需要被做的事情。 PL/SQL 块可以包含 SQL 和 PL/SQL 语句,并且可以定义变量、光标、表达式等 PL/SQL 结构。你也可以调用一个 PL/SQL 过程或一个 Java 过程。
• 另外,行触发器用相关的名字来访问由触发器处理的行的 old 和 new 列值。
• 注:触发器的大小不能超过 32 K。
定义触发器:
CREATE OR REPLACE TRIGGER trigger_name
Timing event1[OR event2OR event3]
ON table_name
Trigger_body
举例1:
CREATE OR REPLACE TRIGGER secure_person
BEFORE INSERT ON person
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 insert
into personS table onlyduring business hours.’);
END IF;
END;
/
举例2:
CREATE OR REPLACE TRIGGER secure_person
BEFORE INSERT OR UPDATE OR DELETE ON person
BEGIN
IF (TO_CHAR (SYSDATE,’DY’) IN (’SAT’,’SUN’))
OR(TO_CHAR (SYSDATE, ’HH24’)
NOT BETWEEN ’08’AND ’18’)THEN
IF DELETING THEN
RAISE_APPLICATION_ERROR (-20502,’You may delete from
person table only during business hours.’);
ELSIF INSERTING THEN
RAISE_APPLICATION_ERROR (-20500,’You may insert into
person table only during business hours.’);
ELSIF UPDATING (‘SALARY’) THEN
RAISE_APPLICATION_ERROR (-20503,’You may update SALARY
only during business hours.’);
ELSE RAISE_APPLICATION_ERROR (-20504,’You may
Update person table only during normal hours.’);
END IF;
END IF;
END;
/
行触发器:
CREATE[OR REPLACE] TRIGGER trigger_name
timing event1 [OR event2 OR event3]
ON table_name
[REFERENCING OLD AS old| NEW AS new]
FOR EACH ROW
[WHEN (condition)]
Trigger_body
举例1:
CREATE OR REPLACE TRIGGER restrict_age
BEFORE INSERT OR UPDATE OF age ON person
FOR EACH ROW
BEGIN
IF NOT (:NEW.per_id IN (’AD_PRES’, ’AD_VP’))
AND :NEW.age > 25 THEN
RAISE_APPLICATION_ERROR (-20202,’person can
not in this amount’);
END IF;
END;
/
举例2:
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;
/
OLD 和 NEW 限定词只在行触发器中可用。在每一个 SQL 和 PL/SQL 语句中用冒号 (:) 前缀这些限定词。如果这些限定词在 WHEN 限制条件中被引用则无冒号 (:) 前缀。
举例3:
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 and NEW 限定词作为前缀引用一个列的值。
数据操纵 OLD 值 NEW 值
INSERT NULL 插入的值
UPDATE 更新前的值 更新后的值
DELETE 删除前的值 NULL
注:如果你在较大的表上做许多的更新,行触发器可能会降低性能。