©
Ce document utilise Manuel du site Web PHP chinois Libérer
CREATE TRIGGER name { BEFORE | AFTER } { event [ OR ... ] } ON table [ FOR [ EACH ] { ROW | STATEMENT } ] [ WHEN ( condition ) ] EXECUTE PROCEDURE function_name ( arguments )
CREATE TRIGGER创建一个新的触发器。触发器将与指定表关联并且将在特定事件发生时执行声明的function_name函数。
触发器可以声明为在对记录进行操作之前(在检查约束之前和INSERT,UPDATE,DELETE执行前) 或操作完成之后(在检查约束之后和完成INSERT,UPDATE,DELETE操作)触发。如果触发器在事件之前, 触发器可能略过当前记录的操作或改变被插入的记录(只对INSERT,UPDATE操作有效)。 如果触发器在事件之后,所有更改,包括其他触发器的影响都是"可见"的。
一个被标记为FOR EACH ROW的触发器为操作修改的每一行都调用一次。比如, 一个影响10行的DELETE将导致任何在目标关系上的ON DELETE触发器独立调用10次, 每个被删除的行调用一次。相比之下,一个被标记为FOR EACH STATEMENT的触发器只执行一次, 而不管有多少行被修改。特别是,一个修改零行的操作仍然会导致合适的FOR EACH STATEMENT触发器被执行。
另外,定义触发器来启动TRUNCATE,尽管仅仅 FOR EACH STATEMENT。
另外,一个触发器定义可以声明一个布尔WHEN条件,这将会 被测试来查看触发器是否会被启动。在行级的触发器中,WHEN 条件可以测试一行的旧的和/或新的列值。语句级触发器也可以有 WHEN条件,尽管该特性对他们来说并不是如此有用,因为 条件不能引用表中的任何值。
如果多个同类型的触发器为同一事件做了定义,那么它们将按照字母 顺序被触发。
SELECT并不更改任何行,因此你不能创建 SELECT触发器。这种场合下规则和视图更合适些。
请参考Chapter 36获取更多触发器信息。
赋予新触发器的名称。它必需和任何作用于同一表的触发器不同。
决定该函数是在事件之前还是之后调用。
INSERT, UPDATE, DELETE, 或者 TRUNCATE之一; 这制指定了将会触发触发器的事件。多个事件可以通过使用 OR来声明。
对于UPDATE触发器,可以用该语法来声明一 系列的列:
UPDATE OF column_name1 [, column_name2 ... ]
触发器仅仅在至少有一个列出的列作为更新的目标时才触发。
触发器作用的表名称(可以用模式修饰)。
这些选项声明触发器过程是否为触发器事件影响的每个行触发一次,还是只为每条SQL语句触发一次。 如果都没有声明,那么FOR EACH STATEMENT将是缺省。
一个决定触发函数是否会真正执行的布尔型表达式。若声明 WHEN,函数仅在condition返回true 时被调用。在FOR EACH ROW触发器中, WHEN条件可以参考旧的和/或新的行值的列,通过分别写 OLD.column_name或 NEW.column_name。 当然,INSERT触发器不能参照OLD 并且DELETE触发器不能参照NEW。
当前,WHEN表达式不包括子查询。
一个用户提供的函数,它声明为不接受参数并且返回trigger类型,该函数将在触发器被触发时调用。
一个可选的用逗号分隔的参数列表,它将在触发器执行的时候提供给函数。 这些参数是文本字符串常量。也可以在这里写简单的名字和数值常量,但是它们会被转换成字符串。 请检查实现语言中关于如何在触发器函数中访问触发器参数的描述;这些参数可能和普通的函数参数不同。
要在表上创建一个触发器,用户必需在该表上有TRIGGER权限。
使用DROP TRIGGER删除一个触发器。
一个特定列触发器(FOR UPDATE OF column_name)将会触发,当其 所有列都像UPDATE命令的SET列表一样排列。 即使当触发器未被触发,列值也是可以更改的,因为通过 BEFORE UPDATE触发器对行内容做的更改不会考虑。 相反地,像UPDATE ... SET x = x ...这样的命令会触发一个 列x上的触发器,即使猎德值不改变。
In a BEFORE trigger, the WHEN condition is evaluated just before the function is or would be executed, so using WHEN is not materially different from testing the same condition at the beginning of the trigger function. Note in particular that the NEW row seen by the condition is the current value, as possibly modified by earlier triggers. Also, a BEFORE trigger's WHEN condition is not allowed to examine the system columns of the NEW row (such as oid), because those won't have been set yet. 在一个BEFORE触发器中,WHEN条件尽在函数被执行时 或之前被评估,所以使用WHEN本质上等同于测试相同的条件, 在触发函数的开始。特别注意,条件看到的NEW行是当前值,可 通过早先的触发器来调整。并且,一个BEFORE触发器的 WHEN条件不允许来测试 NEW行的系统列(比如 oid)因为那些还未设置。
在一个AFTER触发器中,WHEN条件尽在行更新发生后 评估,并且决定一个事件是否会在语句末排队来触发触发器。所以当 AFTER触发器的WHEN条件不返回真值, 既没必要让时间排队也没必要在语句末重新抓取行。这可以导致在更改多行的 语句中速度显著提升,若触发器仅仅需要为几行触发。
在PostgreSQL7.3以前,必须把触发器函数声明为返回opaque占位类型, 而不是trigger类型。为了支持加载老的转储文件,CREATE TRIGGER将接受一个声明为返回opaque的函数, 但是它将发出一条NOTICE并且把函数声明的返回类型改成trigger。
每当表accounts的一行要被更新时就执行函数
check_account_update
。
CREATE TRIGGER check_update BEFORE UPDATE ON accounts FOR EACH ROW EXECUTE PROCEDURE check_account_update();
同样,但是若列balance被指定为 UPDATE命令的一个目标,则仅执行函数:
CREATE TRIGGER check_update BEFORE UPDATE OF balance ON accounts FOR EACH ROW EXECUTE PROCEDURE check_account_update();
它仅在列balance有实际上已更改的值时执行函数:
CREATE TRIGGER check_update BEFORE UPDATE ON accounts FOR EACH ROW WHEN (OLD.balance IS DISTINCT FROM NEW.balance) EXECUTE PROCEDURE check_account_update();
调用一个函数来记录accounts更新,但仅在以下情况时更改:
CREATE TRIGGER log_update AFTER UPDATE ON accounts FOR EACH ROW WHEN (OLD.* IS DISTINCT FROM NEW.*) EXECUTE PROCEDURE log_account_update();
Section 36.4包含了一个用C语言写的 完整的触发器函数的例子。
PostgreSQL里的 CREATE TRIGGER语句实现了一个SQL 标准的子集。目前仍然缺少下面的功能:
SQL 允许你为"old"和"new"行或者表定义别名,用于定义触发器的动作 (也就是CREATE TRIGGER ... ON tablename REFERENCING OLD ROW AS somename NEW ROW AS othername ...)。 因为PostgreSQL允许触发器过程以任意数量的用户定义语言进行书写,所以访问数据的工作是用和语言相关的方法实现的。
PostgreSQL只允许为触发的动作执行用户预先定义好的函数。SQL标准允许执行一些其它的命令, 比如拿CREATE TABLE作为触发器动作。这个限止并不难绕开,只要创建一个执行这些命令的用户预定的函数即可。
SQL要求多个触发器应该以创建的时间顺序执行。 PostgreSQL采用的是按照名字顺序, 并认为这样更加方便。
SQL要求必须在级联DELETE完成之后再触发级联删除上的BEFORE DELETE触发器。 PostgreSQL的行为是BEFORE DELETE将永远在删除动作之前触发,即使对于级联删除也是如此, 我们认为这样更一致。 也有一些不可预期的情况,当BEFORE触发器调整行 或者阻止在由参考动作引起的更新时更新。这会导致约束违反或者不遵循 引用约束的存储数据。
用OR给一个触发器声明多个动作是 PostgreSQL对标准的扩展。
为TRUNCATE触发触发器的能力是SQL标准的一个 PostgreSQL扩展。