PostgreSQL - 触发器(TRIGGERS)

  • 简述

    PostgreSQL Triggers是数据库回调函数,当指定的数据库事件发生时自动执行/调用。
    以下是关于 PostgreSQL 触发器的要点 -
    • 可以指定 PostgreSQL 触发器触发
      • 在对一行尝试操作之前(在检查约束并尝试 INSERT、UPDATE 或 DELETE 之前)
      • 操作完成后(检查约束并完成 INSERT、UPDATE 或 DELETE 后)
      • 而不是操作(在视图上的插入、更新或删除的情况下)
    • 对于操作修改的每一行,都会调用一次标记为 FOR EACH ROW 的触发器。相反,标记为 FOR EACH STATEMENT 的触发器只对任何给定操作执行一次,而不管它修改了多少行。
    • WHEN 子句和触发器操作都可以使用表单的引用访问正在插入、删除或更新的行的元素NEW.column-nameOLD.column-name,其中 column-name 是与触发器关联的表中的列的名称。
    • 如果提供了 WHEN 子句,则指定的 PostgreSQL 语句仅对 WHEN 子句为真的行执行。如果未提供 WHEN 子句,则对所有行执行 PostgreSQL 语句。
    • 如果为同一事件定义了多个相同类型的触发器,它们将按名称的字母顺序触发。
    • BEFORE、AFTER 或 INSTEAD OF 关键字确定何时执行触发器操作,与关联行的插入、修改或删除相关。
    • 当与触发器关联的表被删除时,触发器将被自动删除。
    • 要修改的表必须与触发器附加到的表或视图存在于同一数据库中,并且必须只使用tablename, 不是database.tablename.
    • 指定的 CONSTRAINT 选项会创建一个约束触发器。这与常规触发器相同,只是可以使用 SET CONSTRAINTS 调整触发器触发的时间。约束触发器应该在它们实现的约束被违反时引发异常。
  • 句法

    创建一个基本语法trigger如下 -
    
    CREATE  TRIGGER trigger_name [BEFORE|AFTER|INSTEAD OF] event_name
    ON table_name
    [
     -- Trigger logic goes here....
    ];
    
    这里,event_name可能是对上述表的INSERT、DELETE、 UPDATETRUNCATE数据库操作table_name. 您可以选择在表名之后指定 FOR EACH ROW。
    以下是在表的一个或多个指定列上的 UPDATE 操作上创建触发器的语法,如下所示 -
    
    CREATE  TRIGGER trigger_name [BEFORE|AFTER] UPDATE OF column_name
    ON table_name
    [
     -- Trigger logic goes here....
    ];
    
  • 例子

    让我们考虑一个案例,我们希望对插入 COMPANY 表中的每条记录进行审计试验,我们将按如下方式新建(删除 COMPANY 表,如果您已经拥有它)。
    
    testdb=# CREATE TABLE COMPANY(
       ID INT PRIMARY KEY     NOT NULL,
       NAME           TEXT    NOT NULL,
       AGE            INT     NOT NULL,
       ADDRESS        CHAR(50),
       SALARY         REAL
    );
    
    为了保持审计试验,我们将创建一个名为 AUDIT 的新表,只要 COMPANY 表中有一个新记录条目,就会在其中插入日志消息 -
    
    testdb=# CREATE TABLE AUDIT(
       EMP_ID INT NOT NULL,
       ENTRY_DATE TEXT NOT NULL
    );
    
    这里,ID 是AUDIT 记录ID,EMP_ID 是ID,它来自COMPANY 表,DATE 将保留记录在COMPANY 表中创建时的时间戳。所以现在,让我们在 COMPANY 表上创建一个触发器,如下所示 -
    
    testdb=# CREATE TRIGGER example_trigger AFTER INSERT ON COMPANY
    FOR EACH ROW EXECUTE PROCEDURE auditlogfunc();
    
    其中 auditlogfunc() 是 PostgreSQLprocedure并具有以下定义 -
    
    CREATE OR REPLACE FUNCTION auditlogfunc() RETURNS TRIGGER AS $example_table$
       BEGIN
          INSERT INTO AUDIT(EMP_ID, ENTRY_DATE) VALUES (new.ID, current_timestamp);
          RETURN NEW;
       END;
    $example_table$ LANGUAGE plpgsql;
    
    现在,我们将开始实际工作。让我们开始在 COMPANY 表中插入记录,这将导致在 AUDIT 表中创建审计日志记录。因此,让我们在 COMPANY 表中创建一条记录,如下所示 -
    
    testdb=# INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
    VALUES (1, 'Paul', 32, 'California', 20000.00 );
    
    这将在 COMPANY 表中创建一条记录,如下所示 -
    
     id | name | age | address      | salary
    ----+------+-----+--------------+--------
      1 | Paul |  32 | California   |  20000
    同时,将在 AUDIT 表中创建一条记录。该记录是触发器的结果,它是我们在 COMPANY 表上的 INSERT 操作中创建的。同样,您可以根据您的要求在 UPDATE 和 DELETE 操作上创建触发器。
    
     emp_id |          entry_date
    --------+-------------------------------
          1 | 2013-05-05 15:49:59.968+05:30
    (1 row)
    
  • 列出触发器

    您可以列出当前数据库中的所有触发器pg_trigger表格如下 -
    
    testdb=# SELECT * FROM pg_trigger;
    
    上面给出的 PostgreSQL 语句将列出所有触发器。
    如果要列出特定表上的触发器,请使用带有表名的 AND 子句,如下所示 -
    
    testdb=# SELECT tgname FROM pg_trigger, pg_class WHERE tgrelid=pg_class.oid AND relname='company';
    
    上面给出的 PostgreSQL 语句也将只列出一个条目,如下所示 -
    
         tgname
    -----------------
     example_trigger
    (1 row)
    
  • 删除触发器

    以下是 DROP 命令,可用于删除现有触发器 -
    
    testdb=# DROP TRIGGER trigger_name;