📜  PL / SQL-触发器

📅  最后修改于: 2020-11-26 05:59:43             🧑  作者: Mango


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

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

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

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

可以在与事件关联的表,视图,模式或数据库上定义触发器。

扳机的好处

可以出于以下目的编写触发器-

  • 自动生成一些派生的列值
  • 加强参照完整性
  • 事件记录并存储有关表访问的信息
  • 稽核
  • 表的同步复制
  • 施加安全授权
  • 防止无效交易

创建触发器

创建触发器的语法是-

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; 

哪里,

  • CREATE [OR REPLACE] TRIGGER TRIGGER_NAME -创建或与TRIGGER_NAME替换现有触发器。

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

  • {插入[OR] |更新[OR] | DELETE}-这指定DML操作。

  • [OF col_name]-这指定将更新的列名。

  • [ON table_name]-这指定与触发器关联的表的名称。

  • [以AS的新旧名称重新命名]-这使您可以引用各种DML语句的新旧值,例如INSERT,UPDATE和DELETE。

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

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

首先,我们将使用在先前各章中创建并使用的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操作而触发。此触发器将显示旧值和新值之间的薪金差-

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