CREATE TRIGGER

Name

CREATE TRIGGER  --  定义一个新的触发器

Synopsis

CREATE TRIGGER name {
    BEFORE | AFTER } { event [OR ...] }
    ON table [ FOR EACH { ROW | STATEMENT } ]
    EXECUTE PROCEDURE func ( arguments )
  

输入

name

赋予新触发器的名称.它必需和任何作用于同一表的触发器不同.

BEFORE
AFTER

决定该函数是在事件之前还是之后调用。

event

INSERTDELETEUPDATE 其中之一. 它声明击发触发器的事件。多个事件可以用 OR 声明。

table

触发器作用的表名称(可能用大纲修饰).

FOR EACH ROW
FOR EACH STATEMENT

这些选项声明触发器过程是否为触发器事件影响的每个行触发一次, 还是只为每条 SQL 语句触发一次。如果都没有声明, FOR EACH STATEMENT 是缺省。

func

一个用户提供的函数,它声明为不接受参数并且返回 trigger 类型.

arguments

一个可选的用逗号分隔的参数列表,它将在触发器执行的时候提供给函数, 以及还有标准的触发器数据,比如新旧元组内容.这些参数是文本字串常量. 也可以在这里写简单的名字和数值常量,但是它们会被转换成字串. 请注意这些参数不是以普通函数的形式提供的(因为触发器过程必须声明 为接受零个参数),这些参数是通过 TG_ARGV 数组访问的。

输出

CREATE

如果触发器成功创建,返回此信息.

描述

CREATE TRIGGER 将向现有数据库中增加一个新的触发器. 触发器将与表 table 相联并且将执行声明的函数 func

触发器可以声明为在对记录进行操作之前 在检查约束之前和 INSERTUPDATEDELETE 执行前)或之后(在检 查约束之后和完成 INSERTUPDATEDELETE 操作)触发. 如果触发器在事件之前,触发器可能略过当前记录 的操作或改变被插入的(当前)记录(只对 INSERTUPDATE 操作有效). 如果触发器在事件之后,所有更改,包括最后的插入, 更新或删除对触发器都是"可见"的.

一个 FOR EACH ROW 执行指定操作的触发器 为操作修改的每一行都调用一次。比如,一个影响 10 行的 DELETE 将导致任何在目标关系上的 ON DELETE 触发器独立调用 10 次, 每个被删除的元组一次。相比之下,一个为指定操作 FOR EACH STATEMENT 的触发器只是为任何操作执行一次,不管有多少行被修改。

如果多个同类型的触发器为同样事件做了定义, 那么它们将按照字母顺序被激活.

SELECT 并不更改任何行,因此你不能创建 SELECT 触发器.这种场合下规则和视图更合适些.

请参考 PostgreSQL 程序员手册中SPI 和触发器章节获取更多信息.

注意

要在一个表上创建一个触发器,用户必需在该表上有 TRIGGER 权限.

PostgreSQL 版本 7.3 以前, 我们必须把触发器函数声明为返回占位类型 opaque, 而不是 trigger。为了支持装载老的转储文件, CREATE TRIGGER 将接受一个声明为返回 opaque 的函数, 但是它将发出一条 NOTICE 并且把函数声明的返回类型改成 trigger

请参考 DROP TRIGGER 获取如何删除触发器的信息.

例子

在插入或更新表 films 之前检查一下声明的分销商代码是否存在于 distributors 表中:

CREATE TRIGGER if_dist_exists
    BEFORE INSERT OR UPDATE ON films FOR EACH ROW
    EXECUTE PROCEDURE check_primary_key ('did', 'distributors', 'did');
   

在删除或更新一个分销商的内容之前, 将所有记录移到表 films 中:

CREATE TRIGGER if_film_exists 
    BEFORE DELETE OR UPDATE ON distributors FOR EACH ROW
    EXECUTE PROCEDURE check_foreign_key (1, 'CASCADE', 'did', 'films', 'did');
   

第二给例子也可以用一个外键实现,就象∶

CREATE TABLE distributors (
    did      DECIMAL(3),
    name     VARCHAR(40),
    CONSTRAINT if_film_exists
    FOREIGN KEY(did) REFERENCES films
    ON UPDATE CASCADE ON DELETE CASCADE
);

兼容性

SQL92

SQL92 里没有 CREATE TRIGGER语句.

SQL99

PostgreSQL 里的 CREATE TRIGGER 语句实现了一个 SQL99 标准的子集. 目前仍然缺少下面的功能∶

  • SQL99 允许触发器为指定的字段的更新进行触发(也就是说, AFTER UPDATE OF col1, col2).

  • SQL99 允许你为 "old""new" 行或者表 定义别名,用于定义触发器的动作(也就是说, CREATE TRIGGER ... ON tablename REFERENCING OLD ROW AS somename NEW ROW AS othername ...).因为 PostgreSQL 允许触发器过程以任意数量的用户定义语言进行书写,所以访问数据的工作 是用和语言相关的方法实现的.

  • PostgreSQL 只允许为触发的动作 执行存储的过程.SQL99 允许执行一些其他的 SQL 命令, 比如那 CREATE TABLE 作为触发器动作. 这个限止并不难绕开,只要创建一个执行这些命令的存储过程即可.

SQL99 要求多个触发器应该以创建的时间顺序执行. PostgreSQL 采用的是按照名字顺序, 我们认为这样更加方便.

又见

CREATE FUNCTION, ALTER TRIGGER, DROP TRIGGER, PostgreSQL 程序员手册