域名 AXUM.RS 将于 2025 年 10 月到期。我们无意再对其进行续费,如果你有意接续这个域名,请与我们取得联系。
  • AXUM.RS 现仅需人民币 3000 元(大写:叁仟元整。接受适度议价
  • 按照行业规则,AXUM.RS 到期后,大概率会进入长时间的赎回期,该期间内,如果你想拥有该域名,将要付出高额的费用
  • 我们已启用 AXUM.EU.ORG 域名,并将持续运营
  • 仅接受微信或支付宝交易
如果你对 AXUM.RS 有兴趣,请和我们进行联系:

触发器

本章将讨论触发器,包括:创建、删除、更新、禁用、启用触发器等知识。

简介

触发器是与表关联的特殊的用户自定义函数。要创建新的触发器,首先定义一个触发器函数,然后将该触发器函数绑定到表。

PosgreSQL 有主要有两种触发器:

  • 行级触发器
  • 语句级触发器

它们的区别在于调用触发器的次数和时间。比如发出修改20行的 UPDATE 语句,行级触发器将被调用20次,而语句级触发器将只调用1次。

可以指定触发器是在事件之前还是之后调用。如果在事件之前调用,它可以跳过当前行的操作,甚至更改正在修改或插入的行。如果在事件之后调用,则所有更改都可供触发器使用

如果数据库被各种应用程序访问,并且希望在数据库中保持跨应用功能,只要表的数据被修改,触发器就会自动运行。例如,希望保留数据历史记录,而不要求应用程序具有检查每个事件(比如 INSERTUPDATE)的逻辑。

此外,还可以使用触发器来维护复杂的数据完整性规则,这些规则除了数据库级别之外无法在其它地方实现。比如,当 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 触发器函数名
  • BEFORE:在事件前触发
  • AFTER:在事件后触发

示例数据:

-- 雇员表
DROP TABLE IF EXISTS employees;

CREATE TABLE employees(
   id INT GENERATED ALWAYS AS IDENTITY,
   first_name VARCHAR(40) NOT NULL,
   last_name VARCHAR(40) NOT NULL,
   PRIMARY KEY(id)
);

-- 当雇员姓名发生更改时,将更改记录保存在 employee_audits 表中
CREATE TABLE employee_audits (
   id INT GENERATED ALWAYS AS IDENTITY,
   employee_id INT NOT NULL,
   last_name VARCHAR(40) NOT NULL,
   changed_on TIMESTAMP(6) NOT NULL
);

创建名为 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 表示更新后的行。

创建 last_name_changes触发器:

  • 绑定到 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 对触发器进行重命名:

ALTER TRIGGER 触发器名称
ON 表名 
RENAME TO 新的触发器名称;

注意,它能做的只有这个功能。如果要修改触发器的定义,你需要在事务中先删除、再重新创建:

使用 ALTER TABLE DISABLE|ENABLE TRIGGER 来禁用/启用触发器:

ALTER TABLE 表名
DISABLE | ENABLE TRIGGER 触发器名 | ALL
  • DISABLE:禁用触发器
  • ENABLE:启用触发器
  • 触发器名:禁用/启用指定的触发器
  • ALL:禁用/启用全部触发器
要查看完整内容,请先登录