PL/SQL - Triggers
在本章中,我们将讨论 PL/SQL 中的 Triggers。Triggers 是存储的程序,当某些事件发生时,它们会自动执行或触发。Triggers 实际上是为响应以下任何事件而编写的 −
数据库操作 (DML) 语句 (DELETE、INSERT 或 UPDATE)
数据库定义 (DDL) 语句 (CREATE、ALTER 或 DROP)。
数据库操作 (SERVERERROR、LOGON、LOGOFF、STARTUP 或 SHUTDOWN)。
Triggers 可以定义在与事件关联的 table、view、schema 或 database 上。
Triggers 的优势
Triggers 可以为以下目的编写 −
- 自动生成某些派生列值
- 强制执行引用完整性
- 事件日志记录和存储表访问信息
- 审计
- 表的同步复制
- 实施安全授权
- 防止无效事务
创建触发器
创建触发器的语法如下 −
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) − 为触发器提供触发条件。此子句仅适用于行级触发器。
示例
首先,我们将使用前几章中创建和使用的 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 表创建一个 行级 触发器,该触发器会在对 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);
dbms_output.put_line('新薪资: ' || :NEW.salary);
dbms_output.put_line('薪资差异: ' || 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