PL/SQL触发器

2024年11月21日 PL/SQL触发器 极客笔记

PL/SQL触发器

触发器是由Oracle引擎在特定事件发生时自动调用的。当特定条件匹配时,触发器被存储在数据库中并重复调用。

触发器是存储程序,当发生某个事件时,它们将自动执行或触发。

触发器被编写为响应以下任何事件而执行。

  • 数据库操作(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的现有触发器。
  • {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):这为触发器将触发的行提供了条件。此子句仅对行级触发器有效。

PL/SQL触发器示例

让我们以一个简单的示例来演示触发器。在此示例中,我们使用以下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:

由于这是一个新记录,旧的薪水不可用,所以上述结果为null。现在让我们在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 

本文链接:http://so.lmcjl.com/news/18243/

展开阅读全文