PL / SQL - 触发器

在本章中,我们将讨论PL/SQL中的触发器.触发器是存储的程序,在某些事件发生时会自动执行或触发.事实上,触发器被编写为响应以下任何事件而执行 :

  • A 数据库操作(DML)语句(DELETE,INSERT或UPDATE)

  • 数据库定义(DDL)语句(CREATE,ALTER或DROP).

  • 数据库操作(SERVERERROR,LOGON,LOGOFF,STARTUP或SHUTDOWN).

可以在与事件关联的表,视图,架构或数据库上定义触发器.

触发器的好处

触发器可以用于以下目的 :

  • 自动生成一些派生列值

  • 实施参照完整性

  • 事件记录和存储表访问信息

  • 审核

  • 表的同步复制

  • 强制执行安全授权

  • 防止无效的transacti ons

创建触发器

创建触发器的语法是 :

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;

其中,

  • 创建[或替换] ] TRIGGER trigger_name : 使用 trigger_name 创建或替换现有触发器.

  • {BEFORE |之后| INSTEAD OF} : 这指定何时执行触发器. INSTEAD OF子句用于在视图上创建触发器.

  • {INSERT [OR] |更新[或] | DELETE} : 这指定了DML操作.

  • [OF col_name] : 这指定了要更新的列名.

  • [ON table_name] : 这指定了与触发器关联的表的名称.

  • [引用旧的新的]和减号;这允许您为各种DML语句引用新旧值,例如INSERT,UPDATE和DELETE.

  • [FOR EACH ROW] : 这指定了行级触发器,即,将对受影响的每一行执行触发器.否则,触发器将在执行SQL语句时执行一次,这称为表级触发器.

  • WHEN(condition) : 这为触发器将触发的行提供了条件.此子句仅对行级触发器有效.

示例

首先,我们将使用我们在前面章节中创建和使用的CUSTOMERS表 :

Select * from customers;  

+----+----------+-----+-----------+----------+ 
| ID | NAME     | AGE | ADDRESS   | SALARY   | 
+----+----------+-----+-----------+----------+ 
|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 | 
|  2 | Khilan   |  25 | Delhi     |  1500.00 | 
|  3 | kaushik  |  23 | Kota      |  2000.00 | 
|  4 | Chaitali |  25 | Mumbai    |  6500.00 | 
|  5 | Hardik   |  27 | Bhopal    |  8500.00 | 
|  6 | Komal    |  22 | MP        |  4500.00 | 
+----+----------+-----+-----------+----------+

以下程序为customers表创建行级触发器,触发INSERT或UPDATE或DELETE操作CUSTOMERS表.此触发器将显示旧值和新值之间的工资差异 :

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提示符下执行上述代码时,它会产生以下结果 :

Trigger created.

以下几点需要考虑:

  • OLD和NEW引用不适用于表级触发器,而是可以将它们用于记录级触发器.

  • 如果你想要在同一个触发器中查询表,然后你应该使用AFTER关键字,因为触发器只有在应用了初始更改并且表恢复到一致状态后才能查询表或再次更改表.

  • 上面的触发器是以这样的方式编写的,它会在表上的任何DELETE或INSERT或UPDATE操作之前触发,但你可以在单个或多个操作上编写触发器,例如BEFORE DELETE,每当使用表上的DELETE操作删除记录时将触发.

触发触发器

让我们在CUSTOMERS表上执行一些DML操作.这是一个INSERT语句,它将在表中创建一个新记录 :

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) 
VALUES (7, 'Kriti', 22, 'HP', 7500.00 );

当在CUSTOMERS表中创建记录时,上面的创建触发器 display_salary_changes 将被触发,它将显示以下内容结果 :

Old salary: 
New salary: 7500 
Salary difference:

因为这是一条新记录,旧工资不可用,上述结果为空.现在让我们在CUSTOMERS表上再执行一次DML操作. UPDATE语句将更新表中的现有记录 :

UPDATE customers 
SET salary = salary + 500 
WHERE id = 2;

当在CUSTOMERS表中更新记录时,上面的创建触发器 display_salary_changes 将被触发,它将显示以下内容结果 :

Old salary: 1500 
New salary: 2000 
Salary difference: 500