zoukankan      html  css  js  c++  java
  • psql-08表:触发器

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

    //创建一个对student表的操作记录表
    create table log(
      update_time timestamp,      //操作时间
      db_user varchar(40),          //操作的数据库用户名
      opr_type varchar(6)           //操作类型
    );
    
    //创建触发器函数
    create function log_trigger()
    returns trigger as
    $$
    begin
      insert into log values(now(), user, tg_op);           //user即为当前用户名; to_op是触发器函数中的特殊变量,代表DML操作类型
      return null;
    end;
    $$
    language 'plpgsql';
    
    • 语句级触发器:执行每个SQL时,只执行一次;
    //创建一个语句级触发器
    create trigger log_trigger
      after insert or delete or update on student
      for statement execute procedure log_trigger();   //statement
    
    之后一个SQL语句无论是插入多条数据,删除多条数据或者更新删除不存在的数据;只要执行成功一个SQL语句,就会触发一次;
    
    • 行级触发器: 以SQL语句操作后作用到的n行而触发n次;
    create trigger log_trigger2
      after insert or delete or update on student
      for row execute procedure log_trigger();
    

    before触发器和after触发器

    • 语句级别的before触发器在语句开始做任何事情之前就触发;
    • 语句级别的after触发器在语句结束时触发;
    • 行级别的before触发器在特定进行操作之前触发;
    • 行级别的after触发器在语句结束时触发,但会在任何语句级别的after触发器触发之前触发;
    //before触发器可以直接修改new值以改变实际的更新值
    
    create function student_new_name_trigger()
    returns trigger as
    '     //$$
    begin
      new.student_name = new.student_name || new.student_no;
      return new;
    end;
    '    //$$
    language 'plpgsql';
    
    //
    create trigger new_name_trigger
      before insert or update on student
      for each row execute procedure student_new_name_trigger();
    
    //保存的数据student_name会变成要输入的值拼接上student_no
    

    触发器的行为

    • 触发器函数都有返回值;
    • 语句级别的触发器总是返回null,即写为return null;如果没有写会导致出错;
    • 行级beforeinstead of这类行级触发器:
      * 如果返回null,则忽略对当前行的操作;
      * 如果返回非null的行,对insert,update操作来说,返回的行为将成为插入或更新的行;
    • 行级after触发器,其返回值会被忽略;
    • 如果同一事件上有多个触发器,按触发器的名字顺序来触发;
    • 对于行级beforeinstead of这类行级触发器:
      * 每个触发器返回的行将成为下一个触发器的输入;
      * 返回内容为空的话,该行上其他行触发器也不会被触发;

    事件触发器

    • 用于弥补PostgreSQL以前版本不支持DDL触发器功能;目前,其支持三种DDL事件;
      * ddl_command_start: 一个DDL开始执行前被触发;
      * ddl_command_end: 一个DDL执行完之后被触发;
      * sql_drop: 删除一个数据库对象前被触发;
    • 由于事件触发器权限较大,所以只有超级用户才能创建修改事件触发器;

    创建事件触发器

    • 事件触发器函数的返回类型是event_trigger与普通触发器函数返回类型(trigger)不同;
    //一个禁止所有DDL语句的例子
    create or replace function abort_any_command()
      returns event_trigger
    language plpgsql
    as 
    $$
    begin 
      raise exception 'command % is disabled', tg_tag;
    end;
    $$;
    
    //
    create event trigger abort_ddl on ddl_command_start
    execute procedure abort_any_command();
    
    //在postgresq中truncate事件是使用普通触发器触发的,事件触发器不会触发truncate table;
    
    //禁止上面定义的事件触发器
    alter event trigger abort_ddl disable;
    
    
    • 可以从表pg_evnet_trigger中查看已经定义的触发器;

    变量

    • 事件触发器函数仅仅支持以下变量
    • tg_event:为ddl_command_start,ddl_command_end,sql_drop之一;
    • tg_tag: 具体的哪种DDL操作,如:create table, drop table等;

    修改事件触发器

    alter event trigger name [disable | enable];
    alter event trigger name enable [replica | always];
    alter event trigger name owner to new_owner;
    alter event trigger name rename to new_name;
    

    事件触发器记录数据库中对象删除的审计日志

    //记录信息表
    create table log_drop_objects (
      op_time timestamp,
      ddl_tag text,
      classid oid,
      objid oid,
      objectsubid oid,
      object_type text,
      schme_name text,
      object_name text,
      object_identity text
    );
    
    
    //
    create function event_trigger_log_drops()
      returns event_trigger 
      language plpgsql as
    $$
    declare
       obj record;
    begin
      insert into log_drop_objects select now(), tg_tag, classid, objid, objsubid, object_type,
          schema_name, object_name, object_identity from pg_event_trigger_dropped_objects();
    end
    $$;
    
    //
    create event trigger event_trigger_log_drops
      on sql_drop
      execute procedure event_trigger_log_drops();
    
    //创建一张测试表
    create table test (id int primary key, note varchar(20));
    
    //修改字段或删除表再查看记录表中的记录
    alter table test drop column note;
    

    表空间

    • 表空间实际上是为表指定一个存储的目录;
    • 创建数据库时可以为数据库指定默认的表空间;创建表和索引时可以指定表空间;

    使用

    • 创建:
    create tablespace tablespace_name [owner user_name] location 'directory';
    
    //
    create tablespace tbs_data location '/data/pgdata';
    
    • 创建数据库时指定
    create database db01 set tablespace tbs_data;
    
    • 改变数据库默认空间
    //在此操作时保证没有其他人连接此数据库,否则会报错;
    alter database db01 set tablespace tbs_data;
    
    //数据中已经有的表的表空间不会改变;
    
    • 建表的时候指定表空间
    create table test01 (id int, note text) tablespace tbs_data;
    
    • 创建索引时指定表空间
    create index idx_test01_id on test01(id) tablespace tbs_data;
    
    • 建唯一约束时可以指定约束索引的表空间
    alter table test01 add constraint unique_test01_id unique(id) using index tablespace tbs_data;
    
    • 增加主键时也可以指定主键索引的表空间
    alter table test01 add constraint pk_test01_id primary key(id) using index tablespace tbs_data;
    
    • 把表从一个空间移动到另一个表空间
    //注意在移动表时候会锁表,此时所有对表的操作都会被阻塞;
    alter table test01 set tablespace pg_default;
    
  • 相关阅读:
    策略模式精讲
    工厂模式精讲
    单例模式精讲
    原型模式精讲
    CoreJava学习第五课 --- 进入第二阶段:面向对象编程思想
    CoreJava学习第四课-数组
    CoreJava学习第三课
    CoreJava学习第一课
    Oracle练习题一
    JDBC第一课-简介及开发第一个JDBC程序
  • 原文地址:https://www.cnblogs.com/jinkspeng/p/5043451.html
Copyright © 2011-2022 走看看