PostgreSQL 创建触发器、行级触发器、语句级触发器、触发器内置变量

PostgreSQL 支持触发器功能,触发器与表或者视图进行关联,当表或者视图上的某个事件发生时,指定的触发器函数将被调用。

触发器语法:

CREATE [ CONSTRAINT ] TRIGGER name { BEFORE | AFTER | INSTEAD OF } { event [ OR ... ] }
    ON table_name
    [ FROM referenced_table_name ]
    [ NOT DEFERRABLE | [ DEFERRABLE ] [ INITIALLY IMMEDIATE | INITIALLY DEFERRED ] ]
    [ REFERENCING { { OLD | NEW } TABLE [ AS ] transition_relation_name } [ ... ] ]
    [ FOR [ EACH ] { ROW | STATEMENT } ]
    [ WHEN ( condition ) ]
    EXECUTE { FUNCTION | PROCEDURE } function_name ( arguments )

触发器支持的 event 事件类型包含:

  • insert
  • update
  • delete
  • truncate

触发器的触发时机包含:

  • before,在事件执行之前触发
  • after,在事件执行之后触发
  • instead of

1. 行级触发器

下面通过一个示例来了解触发的创建以及使用,创建一个触发器,实现表 t1 的 insert 操作同步到 t2。

(1)创建表 t1、t2

create table t1(id int, name text);
create table t2(id int, name text);

(2)创建函数,实现 t1 的 insert 操作同步到 t2

create or replace function myfunc_insert() returns trigger AS $mytable$
   begin
      insert into t2(id, name) values (new.id, new.name);
      return new;
   end;
$mytable$ LANGUAGE plpgsql;

(3)创建触发器

-- after 类型
create trigger mytrigger after insert on t1 for each row execute function myfunc_insert();


-- before 类型
create trigger mytrigger before insert on t1 for each row execute function myfunc_insert();

2. 语句级触发器

创建 log 表,记录语句执行日志:

create table mylog(id serial, ts timestamp, op text);

创建语句级触发器调用的函数:

create or replace function myfunc_insert() returns trigger AS $mytable$
   begin
      insert into mylog(ts, op) values (now(), TG_OP);
      return new;
   end;
$mytable$ LANGUAGE plpgsql;

创建语句级触发器:

create trigger mytrigger2
    after insert on t1
    referencing new table as inserted
    for each statement
    execute function myfunc_insert();

3. 触发器的内置变量

触发器在被调用时,系统会自动传递一些数据给它,这些数据包括触发触发器的事件类型(例如INSERT或UPDATE),对于行级触发器,还包括NEW数据行(对于INSERT和UPDATE触发器)和OLD数据行(对于UPDATE和DELETE触发器)。每种可以用来书写触发器函数的语言都提供了取这些数据的方法。

当一个 PL/pgSQL 函数作为一个触发器被调用时,系统自动在最外层的块创建一些特殊的变量。这些变量分别是:

  1. NEW,数据类型是 RECORD。对于行级触发器,它存有 INSERT 或 UPDATE 操作产生的新的数据行。对于语句级触发器,它的值是 NULL。
  2. OLD,数据类型是 RECORD。对于行级触发器,它存有被 UPDATE 或 DELETE 操作修改或删除的旧的数据行。对于语句级触发器,它的值是 NULL。
  3. TG_NAME,数据类型是 name,它保存实际被调用的触发器的名字。
  4. TG_WHEN,数据类型是 text,根据触发器定义信息的不同,它的值是 BEFORE 或 AFTER。
  5. TG_LEVEL,数据类型是 text,根据触发器定义信息的不同,它的值是 ROW 或 STATEMENT。
  6. TG_OP,数据类型是 text,它的值是 INSERT、UPDATE 或 DELETE,表示触发触发器的操作类型。
  7. TG_RELID,数据类型是 oid,表示触发器作用的表的 oid。
  8. TG_RELNAME,数据类型是 name,表示触发器作用的表的名字。它与下面的变量 TG_TABLE_NAME的作用是一样的。
  9. TG_TABLE_NAME,数据类型是 name,表示触发器作用的表的名字。
  10. TG_TABLE_SCHEMA,数据类型是 name,表示触发器作用的表所在的模式。
  11. TG_NARGS,数据类型是 integer,表示 CREATE TRIGGER 命令传给触发器过程的参数的个数。
  12. TG_ARGV[],数据类型是 text 类型的数组。表示 CREATE TRIGGER 命令传给触发器过程的所有参数。下标从0开始。TG_ARGV[0]表示第一个参数,TG_ARGV[1]表示第二个参数,以此类推。如果下标小于0或大于等于 tg_nargs,将会返回一个空值。

4. 查询所有的触发器

select * from pg_trigger;

-- 查询触发器的定义
select pg_get_triggerdef(oid) from pg_trigger where tgname='mytrigger';

5. 删除触发器

drop trigger mytrigger on t1;

参考资料:

https://www.postgresql.org/docs/13/sql-createtrigger.html

文章评论

0条评论