PostgreSQL触发器函数


1 触发器函数管理命令

管理函数的快捷命令
\ef 创建一个新的函数。
\df 显示已经创建的函数。
\df+    somefunc 显示这个函数的详细定义
\ef   somefunc 编辑这个函数, 编辑保存退出之后,要执行 \g ,刚才的修改才会生效。
\g  使刚才的修改生效。

查看触发器函数详细定义SQL

\x on;
select * from pg_proc where proname='log_history_insert_trigger';

2 继承式分区-创建触发器函数

2.1 创建触发器函数

在继承式表分区会用到触发器函数,分区表从主表继承,主表不包含数据,不在主表上定义任何检查约束,此时需要通过触发器函数将数据指定相应的分区。

创建主表和分区

create table log_history(id int not null,logdate date not null,num int);
create table log_history_2011(check (logdate >= date'2011-01-01' and logdate < date'2012-01-01')) inherits(log_history);
create table log_history_2012(check (logdate >= date'2012-01-01' and logdate < date'2013-01-01')) inherits(log_history);
create table log_history_2013(check (logdate >= date'2013-01-01' and logdate < date'2014-01-01')) inherits(log_history);
create table log_history_2014(check (logdate >= date'2014-01-01' and logdate < date'2015-01-01')) inherits(log_history);
create table log_history_2015(check (logdate >= date'2015-01-01' and logdate < date'2016-01-01')) inherits(log_history);
create table log_history_2016(check (logdate >= date'2016-01-01' and logdate < date'2017-01-01')) inherits(log_history);
create table log_history_2017(check (logdate >= date'2017-01-01' and logdate < date'2018-01-01')) inherits(log_history);
create table log_history_2018(check (logdate >= date'2018-01-01' and logdate < date'2019-01-01')) inherits(log_history);
create table log_history_2019(check (logdate >= date'2019-01-01' and logdate < date'2020-01-01')) inherits(log_history);
create table log_history_2020(check (logdate >= date'2020-01-01' and logdate < date'2021-01-01')) inherits(log_history);
create table log_history_2021(check (logdate >= date'2021-01-01' and logdate < date'2022-01-01')) inherits(log_history);

此时插入数据不会插入到分区中

postgres=# insert into log_history values(1,'2021-09-01',1);
INSERT 0 1
postgres=# select * from log_history;
 id |  logdate   | num 
----+------------+-----
  1 | 2021-09-01 |   1
(1 row)

postgres=# select * from log_history_2021;
 id | logdate | num 
----+---------+-----
(0 rows)

postgres=# select * from log_history_2021;
 id | logdate | num 
----+---------+-----
(0 rows)

创建触发器函数

#vi log_history_insert_trigger.sql
CREATE OR REPLACE FUNCTION log_history_insert_trigger()
RETURNS TRIGGER AS $$
BEGIN
    IF ( NEW.logdate >= DATE '2011-01-01' AND
         NEW.logdate < DATE '2012-01-01' ) THEN
        INSERT INTO log_history_2011 VALUES (NEW.*);
    ELSIF ( NEW.logdate >= DATE '2012-01-01' AND
            NEW.logdate < DATE '2013-01-01' ) THEN
        INSERT INTO log_history_2012 VALUES (NEW.*);
    ELSIF ( NEW.logdate >= DATE '2013-01-01' AND
            NEW.logdate < DATE '2014-01-01' ) THEN
        INSERT INTO log_history_2013 VALUES (NEW.*);
    ELSIF ( NEW.logdate >= DATE '2014-01-01' AND
            NEW.logdate < DATE '2015-01-01' ) THEN
        INSERT INTO log_history_2014 VALUES (NEW.*);
    ELSIF ( NEW.logdate >= DATE '2016-01-01' AND
            NEW.logdate < DATE '2017-01-01' ) THEN
        INSERT INTO log_history_2016 VALUES (NEW.*);
    ELSIF ( NEW.logdate >= DATE '2017-01-01' AND
            NEW.logdate < DATE '2018-01-01' ) THEN
        INSERT INTO log_history_2017 VALUES (NEW.*);
    ELSIF ( NEW.logdate >= DATE '2018-01-01' AND
            NEW.logdate < DATE '2019-01-01' ) THEN
        INSERT INTO log_history_2018 VALUES (NEW.*);
    ELSIF ( NEW.logdate >= DATE '2019-01-01' AND
            NEW.logdate < DATE '2020-01-01' ) THEN
        INSERT INTO log_history_2019 VALUES (NEW.*);
    ELSIF ( NEW.logdate >= DATE '2021-01-01' AND
            NEW.logdate < DATE '2022-01-01' ) THEN
        INSERT INTO log_history_2021 VALUES (NEW.*);
    ELSE
        RAISE EXCEPTION 'Date out of range.  Fix the log_history_insert_trigger() function!';
    END IF;
    RETURN NULL;
END;
$$
LANGUAGE plpgsql;

创建函数
postgres=# \i log_history_insert_trigger.sql

重新插入数据

postgres=# insert into log_history values(1,'2021-09-01',1);
INSERT 0 1
postgres=# select * from log_history;
 id |  logdate   | num 
----+------------+-----
  1 | 2021-09-01 |   1
(1 row)

postgres=# select * from log_history_2021;
 id |  logdate   | num 
----+------------+-----
  1 | 2021-09-01 |   1
(0 rows)

2.2 更改触发器函数

继承式分区添加2023年的新分区

postgres=# create table log_history_2023(check (logdate >= date'2023-01-01' and logdate < date'2024-01-01')) INHERITS (log_history);
CREATE TABLE
postgres=# select inhrelid::regclass,inhparent::regclass,inhseqno from pg_inherits;
     inhrelid     |  inhparent  | inhseqno 
------------------+-------------+----------
 log_history_2011 | log_history |        1
 log_history_2012 | log_history |        1
 log_history_2013 | log_history |        1
 log_history_2014 | log_history |        1
 log_history_2015 | log_history |        1
 log_history_2016 | log_history |        1
 log_history_2017 | log_history |        1
 log_history_2018 | log_history |        1
 log_history_2019 | log_history |        1
 log_history_2020 | log_history |        1
 log_history_2021 | log_history |        1
 log_history_2023 | log_history |        1

更新触发器函数,添加2023年新分区约束

postgres=# \ef log_history_insert_trigger

#进入编辑模式,添加2023年分区约束
CREATE OR REPLACE FUNCTION public.log_history_insert_trigger()
 RETURNS trigger
 LANGUAGE plpgsql
AS $function$
BEGIN
    IF ( NEW.logdate >= DATE '2011-01-01' AND
         NEW.logdate < DATE '2012-01-01' ) THEN
        INSERT INTO log_history_2011 VALUES (NEW.*);
    ELSIF ( NEW.logdate >= DATE '2012-01-01' AND
            NEW.logdate < DATE '2013-01-01' ) THEN
        INSERT INTO log_history_2012 VALUES (NEW.*);
    ELSIF ( NEW.logdate >= DATE '2013-01-01' AND
            NEW.logdate < DATE '2014-01-01' ) THEN
        INSERT INTO log_history_2013 VALUES (NEW.*);
    ELSIF ( NEW.logdate >= DATE '2014-01-01' AND
            NEW.logdate < DATE '2015-01-01' ) THEN
        INSERT INTO log_history_2014 VALUES (NEW.*);
    ELSIF ( NEW.logdate >= DATE '2016-01-01' AND
            NEW.logdate < DATE '2017-01-01' ) THEN
        INSERT INTO log_history_2016 VALUES (NEW.*);
    ELSIF ( NEW.logdate >= DATE '2017-01-01' AND
            NEW.logdate < DATE '2018-01-01' ) THEN
        INSERT INTO log_history_2017 VALUES (NEW.*);
    ELSIF ( NEW.logdate >= DATE '2018-01-01' AND
            NEW.logdate < DATE '2019-01-01' ) THEN
        INSERT INTO log_history_2018 VALUES (NEW.*);
    ELSIF ( NEW.logdate >= DATE '2019-01-01' AND
            NEW.logdate < DATE '2020-01-01' ) THEN
        INSERT INTO log_history_2019 VALUES (NEW.*);
    ELSIF ( NEW.logdate >= DATE '2021-01-01' AND
            NEW.logdate < DATE '2022-01-01' ) THEN
        INSERT INTO log_history_2021 VALUES (NEW.*);
    ELSIF ( NEW.logdate >= DATE '2022-01-01' AND
            NEW.logdate < DATE '2023-01-01' ) THEN
        INSERT INTO log_history_2022 VALUES (NEW.*);
    ELSIF ( NEW.logdate >= DATE '2023-01-01' AND
            NEW.logdate < DATE '2024-01-01' ) THEN
        INSERT INTO log_history_2023 VALUES (NEW.*);
    ELSE
        RAISE EXCEPTION 'Date out of range.  Fix the log_history_insert_trigger() function!';
    END IF;
    RETURN NULL;
END;
$function$

#然后输入“wq”保存退出

#然后执行\g使触发器函数变更生效
postgres-# \g
CREATE FUNCTION

查看触发器函数定义,可以看到2023年分区已添加

postgres=# \df+ log_history_insert_trigger
List of functions
-[ RECORD 1 ]-------+----------------------------------------------------------------------------------------------
Schema              | public
Name                | log_history_insert_trigger
Result data type    | trigger
Argument data types | 
Type                | func
Volatility          | volatile
Parallel            | unsafe
Owner               | postgres12
Security            | invoker
Access privileges   | 
Language            | plpgsql
Source code         |                                                                                              +
                    | BEGIN                                                                                        +
                    |     IF ( NEW.logdate >= DATE '2011-01-01' AND                                                +
                    |          NEW.logdate < DATE '2012-01-01' ) THEN                                              +
                    |         INSERT INTO log_history_2011 VALUES (NEW.*);                                         +
                    |     ELSIF ( NEW.logdate >= DATE '2012-01-01' AND                                             +
                    |             NEW.logdate < DATE '2013-01-01' ) THEN                                           +
                    |         INSERT INTO log_history_2012 VALUES (NEW.*);                                         +
                    |     ELSIF ( NEW.logdate >= DATE '2013-01-01' AND                                             +
                    |             NEW.logdate < DATE '2014-01-01' ) THEN                                           +
                    |         INSERT INTO log_history_2013 VALUES (NEW.*);                                         +
                    |     ELSIF ( NEW.logdate >= DATE '2014-01-01' AND                                             +
                    |             NEW.logdate < DATE '2015-01-01' ) THEN                                           +
                    |         INSERT INTO log_history_2014 VALUES (NEW.*);                                         +
                    |     ELSIF ( NEW.logdate >= DATE '2016-01-01' AND                                             +
                    |             NEW.logdate < DATE '2017-01-01' ) THEN                                           +
                    |         INSERT INTO log_history_2016 VALUES (NEW.*);                                         +
                    |     ELSIF ( NEW.logdate >= DATE '2017-01-01' AND                                             +
                    |             NEW.logdate < DATE '2018-01-01' ) THEN                                           +
                    |         INSERT INTO log_history_2017 VALUES (NEW.*);                                         +
                    |     ELSIF ( NEW.logdate >= DATE '2018-01-01' AND                                             +
                    |             NEW.logdate < DATE '2019-01-01' ) THEN                                           +
                    |         INSERT INTO log_history_2018 VALUES (NEW.*);                                         +
                    |     ELSIF ( NEW.logdate >= DATE '2019-01-01' AND                                             +
                    |             NEW.logdate < DATE '2020-01-01' ) THEN                                           +
                    |         INSERT INTO log_history_2019 VALUES (NEW.*);                                         +
                    |     ELSIF ( NEW.logdate >= DATE '2021-01-01' AND                                             +
                    |             NEW.logdate < DATE '2022-01-01' ) THEN                                           +
                    |         INSERT INTO log_history_2021 VALUES (NEW.*);                                         +
                    |     ELSIF ( NEW.logdate >= DATE '2022-01-01' AND                                             +
                    |             NEW.logdate < DATE '2023-01-01' ) THEN                                           +
                    |         INSERT INTO log_history_2022 VALUES (NEW.*);                                         +
                    |     ELSIF ( NEW.logdate >= DATE '2023-01-01' AND                                             +
                    |             NEW.logdate < DATE '2024-01-01' ) THEN                                           +
                    |         INSERT INTO log_history_2023 VALUES (NEW.*);                                         +
                    |     ELSE                                                                                     +
                    |         RAISE EXCEPTION 'Date out of range.  Fix the log_history_insert_trigger() function!';+
                    |     END IF;                                                                                  +
                    |     RETURN NULL;                                                                             +
                    | END;                                                                                         +
                    | 
Description         |