- 以美元符号作为引号的字符串常量本章将讨论如何在 PL/pgSQL 编程中使用以美元符号作为引号的字符串常量。
- 块结构本章将讨论 PL/pgSQL 的块结构,同时也会带你编写第一个 PL/pgSQL 程序。
- 变量本章将学习 PL/pgSQL 变量的相关知识。
- 行类型本章将讨论 PL/pgSQL 的行类型。将一个变量声明为行类型之后,它便可以保存数据库中的整行数据。
- 记录类型本章我们讨论 PostgreSQL 的记录类型,它和行类型相似,也可以存储数据库中的整行信息。
- 常量本章将讨论 PL/pgSQL 常量。
- 错误和异常处理本章我们将讨论 PL/pgSQL 的错误和异常处理。
- 控制结构本章将讨论 PL/pgSQL 的控制结构,包括:IF、CASE、LOOP、WHILE LOOP、FOR LOOP、EXIT和CONTINUE等语句。
- 函数本章我们将讨论自定义函数的相关知识,包括:创建函数、函数参数的模式、函数重载、返回表的函数以及删除函数等知识。
- 存储过程本章我们将讨论存储过程。
- 游标本章我们将讨论 PL/pgSQL 的游标以及如何使用它们逐行处理结果集。
- 触发器本章将讨论触发器,包括:创建、删除、更新、禁用、启用触发器等知识。
触发器
- 543
- 2023-08-02 03:09:39
本章将讨论触发器,包括:创建、删除、更新、禁用、启用触发器等知识。
简介
PostgreSQL 触发器是每当与表关联的事件发生时自动调用的函数。事件可以是:INSERT、UPDATE、DELETE 或 TRUNCATE。
触发器是与表关联的特殊的用户自定义函数。要创建新的触发器,首先定义一个触发器函数,然后将该触发器函数绑定到表。
PosgreSQL 有主要有两种触发器:
- 行级触发器
- 语句级触发器
它们的区别在于调用触发器的次数和时间。比如发出修改20行的 UPDATE 语句,行级触发器将被调用20次,而语句级触发器将只调用1次。
可以指定触发器是在事件之前还是之后调用。如果在事件之前调用,它可以跳过当前行的操作,甚至更改正在修改或插入的行。如果在事件之后调用,则所有更改都可供触发器使用
如果数据库被各种应用程序访问,并且希望在数据库中保持跨应用功能,只要表的数据被修改,触发器就会自动运行。例如,希望保留数据历史记录,而不要求应用程序具有检查每个事件(比如 INSERT或UPDATE)的逻辑。
此外,还可以使用触发器来维护复杂的数据完整性规则,这些规则除了数据库级别之外无法在其它地方实现。比如,当 customer 表添加记录的时候,还必须在银行和信用表中创建其它记录。
使用触发器最主要的缺点是,你必须知道触发器存在并了解其逻辑,才能弄清楚数据更改时的影响。
PostgreSQL 扩展了 SQL 标准的触发器:
- 添加了 TRUNCATE事件的触发器
- 允许在视图上定义语句级触发器
- 要求必须使用自定义函数作为触发器操作,而 SQL 标准允许使用任何 SQL 命令
创建触发器
创建触发器分两个步骤:
- 首先,使用 CREATE FUNCTION创建一个触发器函数
- 其次,使用 CREATE TRIGGER将触发器函数绑定到表
触发器函数类似于常规的自定义函数,比较特殊的一点是,触发器函数不接受任何参数,并具有 trigger 类型的返回值。
创建触发器函数的语法如下:
CREATE FUNCTION 触发器函数名() 
   RETURNS TRIGGER 
   LANGUAGE PLPGSQL
AS $$
BEGIN
   -- 触发器逻辑
END $$;
创建触发器的语法如下:
CREATE TRIGGER 触发器名称 
   {BEFORE | AFTER} { 事件 }
   ON 表名
   [FOR [EACH] { ROW | STATEMENT }]
       EXECUTE PROCEDURE 触发器函数名
示例数据:
创建名为 log_last_name_changes的触发器函数:
CREATE OR REPLACE FUNCTION log_last_name_changes()
  RETURNS TRIGGER 
  LANGUAGE PLPGSQL
  AS
$$
BEGIN
	IF NEW.last_name <> OLD.last_name THEN
		 INSERT INTO employee_audits(employee_id,last_name,changed_on)
		 VALUES(OLD.id,OLD.last_name,now());
	END IF;
	RETURN NEW;
END $$;
- OLD表示更新前的行,而- NEW表示更新后的行。
- 绑定到 employees
- 监听 UPDATE事件,并在事件前触发
- 是一个行级触发器
- 触发器函数是 log_last_name_changes()
CREATE TRIGGER last_name_changes
  BEFORE UPDATE
  ON employees
  FOR EACH ROW
  EXECUTE PROCEDURE log_last_name_changes();
删除触发器
使用 DROP TRIGGER 来删除触发器:
DROP TRIGGER [IF EXISTS] 触发器名称 
ON table_name [ CASCADE | RESTRICT ];
修改触发器
ALTER TRIGGER 触发器名称
ON 表名 
RENAME TO 新的触发器名称;
注意,它能做的只有这个功能。如果要修改触发器的定义,你需要在事务中先删除、再重新创建:
BEGIN;
DROP TRIGGER IF EXISTS 触发器名称;
CREATE TRIGGER 触发器名称
  BEFORE UPDATE
  ON 表名
  FOR EACH ROW
  EXECUTE PROCEDURE 触发器函数();
COMMIT;
禁用/启用触发器
ALTER TABLE 表名
DISABLE | ENABLE TRIGGER 触发器名 | ALL
- DISABLE:禁用触发器
- ENABLE:启用触发器
- 触发器名:禁用/启用指定的触发器
- ALL:禁用/启用全部触发器
