PL/SQL触发器

在本章中,咱们将讨论和学习PL/SQL中的触发器。 触发器是存储的程序,在发生某些事件时会自动执行或触发。事实上,触发器是为了响应如下任何事件而被执行的 -sql

  • 数据库操做(DML)语句(DELETEINSERTUPDATE)
  • 数据库定义(DDL)语句(CREATEALTERDROP)。
  • 数据库操做(SERVERERRORLOGONLOGOFFSTARTUPSHUTDOWN)。

能够在事件关联的表,视图,模式或数据库上定义触发器。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语句(如INSERTUPDATEDELETE)引用新值和旧值。
  • [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表上执行的INSERTUPDATEDELETE操做。这个触发器将显示旧值和新值之间的工资差别 -事务

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

  • OLDNEW引用不可用于表级触发器,而是能够将它们用于记录级触发器。
  • 若是要在同一个触发器中查询表,则应该使用AFTER关键字,由于触发器只能在应用初始更改而且表返回一致状态后才能查询表或进行更改。
  • 上面的触发器是这样:在表上执行任何DELETEINSERTUPDATE操做以前触发,可是能够在一个或多个操做上编写触发器,例如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 行。
相关文章
相关标签/搜索