在本章中,咱们将讨论和学习PL/SQL中的触发器。 触发器是存储的程序,在发生某些事件时会自动执行或触发。事实上,触发器是为了响应如下任何事件而被执行的 -sql
DELETE
,INSERT
或UPDATE
)CREATE
,ALTER
或DROP
)。SERVERERROR
,LOGON
,LOGOFF
,STARTUP
或SHUTDOWN
)。能够在事件关联的表,视图,模式或数据库上定义触发器。shell
使用触发器的好处数据库
触发器能够用于如下目的 -安全
建立触发器的语法是 -学习
CREATE [OR REPLACE ] TRIGGER trigger_name {BEFORE | AFTER | INSTEAD OF } {INSERT [OR] | UPDATE [OR] | DELETE} [OF col_name] ON table_name [REFERENCING OLD AS o NEW AS n] [FOR EACH ROW] WHEN (condition) DECLARE Declaration-statements BEGIN Executable-statements EXCEPTION Exception-handling-statements END;
其中,code
CREATE [OR REPLACE] TRIGGER trigger_name
- 使用trigger_name
建立或替换现有的触发器。{BEFORE | AFTER | INSTEAD OF}
- 指定什么时候执行触发器。INSTEAD OF
子句用于在视图上建立触发器。{INSERT [OR] | UPDATE [OR] | DELETE}
- 这指定了DML操做。[OF col_name]
− 这指定了将要更新的列名称。[ON table_name]
- 这指定了与触发器关联的表的名称。[REFERENCING OLD AS o NEW AS n]
- 这容许各类DML语句(如INSERT
,UPDATE
和DELETE
)引用新值和旧值。[FOR EACH ROW]
- 这指定了一个行级别的触发器,即触发器将被执行的每一行受到影响。不然触发器将在执行SQL语句时执行一次,这称为表级触发器。WHEN(condition)
- 这为触发器触发的行提供了一个条件。该子句仅对行级触发器有效。首先,将使用前面章节中建立和使用的CUSTOMERS
表,表的定义和数据以下 -事件
CREATE TABLE CUSTOMERS( ID INT NOT NULL, NAME VARCHAR (20) NOT NULL, AGE INT NOT NULL, ADDRESS CHAR (25), SALARY DECIMAL (18, 2), PRIMARY KEY (ID) ); -- 插入示例数据 INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) VALUES (1, 'Ramesh', 32, 'Ahmedabad', 2000.00 ); INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) VALUES (2, 'Khilan', 25, 'Delhi', 1500.00 ); INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) VALUES (3, 'kaushik', 23, 'Kota', 2000.00 ); INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) VALUES (4, 'Chaitali', 25, 'Mumbai', 6500.00 ); INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) VALUES (5, 'Hardik', 27, 'Bhopal', 8500.00 ); INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) VALUES (6, 'Komal', 22, 'MP', 4500.00 );
下面的程序为customers
表建立一个行级触发器,该触发器将触发在customers
表上执行的INSERT
,UPDATE
或DELETE
操做。这个触发器将显示旧值和新值之间的工资差别 -事务
SET SERVEROUTPUT ON SIZE 999999; CREATE OR REPLACE TRIGGER display_salary_changes BEFORE DELETE OR INSERT OR UPDATE ON customers FOR EACH ROW WHEN (NEW.ID > 0) DECLARE sal_diff number; BEGIN sal_diff := :NEW.salary - :OLD.salary; dbms_output.put_line('Old salary: ' || :OLD.salary); dbms_output.put_line('New salary: ' || :NEW.salary); dbms_output.put_line('Salary difference: ' || sal_diff); END; /
当上面的代码在SQL提示符下执行时,它会产生如下结果 -同步
这里须要考虑如下几点 -it
OLD
和NEW
引用不可用于表级触发器,而是能够将它们用于记录级触发器。AFTER
关键字,由于触发器只能在应用初始更改而且表返回一致状态后才能查询表或进行更改。DELETE
或INSERT
或UPDATE
操做以前触发,可是能够在一个或多个操做上编写触发器,例如BEFORE DELETE
,当表中的一条记录被删除时,自动触发。触发一个触发器
如今,在customers
表上执行一些DML操做。这里以执行一个INSERT
语句做为示例,它将在表中建立一个新记录 -
INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) VALUES (7, 'Hinew', 23, 'Oracle', 9500.00 );
当在CUSTOMERS
表中建立一条记录时,上面的建立触发器display_salary_changes
将被触发,而且将显示如下结果 -
SQL> INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) 2 VALUES (7, 'Hinew', 23, 'Oracle', 9500.00); Old salary: New salary: 9500 Salary difference: 已建立 1 行。 SQL>
由于这是一个新的记录,旧的薪水(salary
)列是不可用的,上述结果为空。下面再向CUSTOMERS
表上执行另外一个更多的DML操做。此次使用UPDATE
语句来更新表中的现有记录 -
UPDATE customers SET salary = salary + 500 WHERE id = 2;
执行上面示例代码,获得如下结果 -
SQL> UPDATE customers 2 SET salary = salary + 500 3 WHERE id = 2; Old salary: 1500 New salary: 2000 Salary difference: 500 已更新 1 行。