4.5 触发器

触发器(Trigger)是由事件自动触发执行的一种特殊的存储过程,触发事件可以是对一个表进行INSERT、UPDATE、DELETE等操作。

触发器经常用于加强数据的完整性约束和业务规则上的约束等。

4.5.1 创建触发器

  1. 创建语法:

    CREATE [ CONSTRAINT ] TRIGGER name { BEFORE | AFTER | INSTEAD OF } { event [ OR ... ] }
      ON table_name
      [ FROM referenced_table_name ]
      { NOT DEFERRABLE | [ DEFERRABLE ] { INITIALLY IMMEDIATE | INITIALLY DEFERRED } }
      [ FOR [ EACH ] { ROW | STATEMENT } ]
      [ WHEN ( condition ) ]
      EXECUTE PROCEDURE function_name ( arguments )
  2. 创建触发器的步骤:

    1. 先为触发器建一个执行函数,此函数的返回类型为触发器类型

    2. 然后建一个触发器

  3. 举例:

    1. 创建两张表:学生表 + 成绩表

      CREATE TABLE student(
        student_no int primary key, 
        student_name varchar(40), 
        age int
      );
      
      CREATE TABLE score (
        student_no int,
        chinese_score int,
        math_score int,
        test_date date
      );
    2. 规则:删除学生表的学生信息之后,自动删除成绩表中的数据

    3. 先创建触发器执行函数

      CREATE OR REPLACE FUNCTION student_delete_trigger()
      RETURNS TRIGGER AS $$
      BEGIN
        DELETE FROM score WHERE student_no = OLD.student_no;
        RETURN OLD;
      END;
      $$
      LANGUAGE plpgsql;
    4. 创建触发器

      CREATE TRIGGER delete_student_trigger
        AFTER DELETE ON student
        FOR EACH ROW EXECUTE PROCEDURE student_delete_trigger ();

4.5.2 语句级触发器与行级触发器

  1. 语句级触发器:执行每个SQL语句时只执行一次

  2. 行级触发器:行级触发器是执行每行SQL语句都会执行一次

  3. 举例:对student表的更新情况做日志记录

    1. 创建表:

      CREATE TABLE log_student(
        update_time  timestamp, --操作的时间
        db_user varchar(40), --操作的数据库用户名
        opr_type varchar(6) --操作类型:insert、delete、update
      );
    2. 创建记录日志触发器

      CREATE FUNCTION log_student_trigger ()
      RETURNS trigger AS
      $$
      BEGIN
        INSERT INTO log_student values(now(), user, TG_OP);
        RETURN NULL;
      END;
      $$
      LANGUAGE "plpgsql";
    3. 创建一个语句级触发器

      CREATE TRIGGER log_student_trigger
        AFTER INSERT OR DELETE OR UPDATE  ON student
        FOR STATEMENT EXECUTE PROCEDURE log_student_trigger ();

      备注:如果一条语句包含多个操作,那么值记录一次

    4. 创建一个行级触发器

      CREATE TRIGGER log_student_trigger2
        AFTER INSERT OR DELETE OR UPDATE  ON student
        FOR ROW EXECUTE PROCEDURE log_student_trigger ();

      备注:一条语句有多个操作,每个操作都会记录

4.5.3 BEFORE触发器与AFTER触发器

  1. BEFORE触发器是在操作之前触发的,包括语句级与行级

  2. AFTER触发器在操作之后触发的,包括语句级与行级

4.5.4 删除触发器

  1. 语法:

    DROP TRIGGER [ IF EXISTS ] name ON table [ CASCADE | RESTRICT ];

    备注:

    IF EXISTS:如果触发器不存在,那么发出一个notice而不是抛出一个错误

    CASCADE:级联删除依赖此触发器的对象

    RESTRICT:默认值,有依赖对象存在就拒绝删除

  2. 删除触发器时,触发器函数不会被删除,删除表时,表上的触发器也会被删除

4.5.5 触发器的行为

  1. 触发器函数有返回值,语句级应该返回null,必须显示地在触发器函数中写RETURN NULL,没写会报错

4.5.6 触发器函数中的特殊变量

  1. NEW:该变量为INSERT/UPDATE操作触发的行级触发器中存储新的数据行,数据类型是“RECORD”。在语句级别的触发器中此变量未分配,DELETE操作触发的行级触发器中此变量也未分配

  2. OLD:该变量为UPDATE/DELETE操作触发的行级触发器中存储原有的数据行,数据类型是“RECORD”。在语句级别的触发器中此变量未分配,INSERT操作触发的行级触发器中此变量也未分配

  3. TG_NAME:数据类型是name类型,该变量包含实际触发的触发器名

  4. TG_WHEN:内容为“BEFORE”或“AFTER”字符串用于指定是BEFORE触发器还是AFTER触发器

  5. TG_LEVEL:内容为“ROW”或“STATEMENT”字符串用于指定是语句级触发器还是行级触发器

  6. TG_OP:内容为“INSERT”“UPDATE”“DELETE”“TRUNCATE”之一的字符串,用于指定DML语句的类型

  7. TG_RELID:触发器所在表的OID

  8. TG_RELNAME:触发器所在表的名称,该变量即将[…]

  9. TG_ARGV[]:为text类型的数组;是CREATE TRIGGER语句中的参数

最后更新于