PostgreSQL 11 新特性之分区表行级触发器

版权声明:本站不全为博主原创文章,欢迎转载,转载记得标明出处。^-^ https://blog.csdn.net/horses/article/details/86085948

文章目录

PosgtreSQL 11 支持分区表上的 FOR EACH ROW 触发器。目前,只能创建 AFTER 触发器,还不支持 BEFORE 触发器。另外,定义触发器时不能指定 WHEN 子句,也就是不能指定触发条件。

首先创建一个分区表和分区:

CREATE TABLE rtable(c1 INT, c2 VARCHAR(10)) PARTITION BY RANGE(c1);
CREATE TABLE rtable100 PARTITION OF rtable FOR VALUES FROM (1) TO (100);

接下来为 rtable 表创建一个行级触发器:

CREATE OR REPLACE FUNCTION rtable_insert_func()
RETURNS TRIGGER AS $$
BEGIN
    RAISE INFO 'INSERT TRIGGER ON %', TG_TABLE_NAME;
	RAISE INFO 'INSERT VALUES: c1=%; c2=%', NEW.c1, NEW.c2;
    RETURN NULL;
END;
$$
LANGUAGE plpgsql;

CREATE TRIGGER rtable_insert_trigger
    AFTER INSERT ON rtable
    FOR EACH ROW EXECUTE FUNCTION rtable_insert_func();

分区表上创建的触发器也会自动为已有的分区和将来添加的分区自动创建相应的触发器。

\d rtable
                      Table "public.rtable"
 Column |         Type          | Collation | Nullable | Default 
--------+-----------------------+-----------+----------+---------
 c1     | integer               |           |          | 
 c2     | character varying(10) |           |          | 
Partition key: RANGE (c1)
Triggers:
    rtable_insert_trigger AFTER INSERT ON rtable FOR EACH ROW EXECUTE PROCEDURE rtable_insert_func()
Number of partitions: 1 (Use \d+ to list them.)

\d rtable100
                    Table "public.rtable100"
 Column |         Type          | Collation | Nullable | Default 
--------+-----------------------+-----------+----------+---------
 c1     | integer               |           |          | 
 c2     | character varying(10) |           |          | 
Partition of: rtable FOR VALUES FROM (1) TO (100)
Triggers:
    rtable_insert_trigger AFTER INSERT ON rtable100 FOR EACH ROW EXECUTE PROCEDURE rtable_insert_func()

插入一条数据,查看触发器的执行情况:

insert into rtable(c1, c2) VALUES(10, 'val10');
INFO:  INSERT TRIGGER ON rtable100
INFO:  INSERT VALUES: c1=10; c2=val10
INSERT 0 1

需要注意的是,分区表 FOR EACH ROW 触发器执行的时候,TG_TABLE_NAME 变量的值是数据所在分区的名称(rtable100),而不是分区表的名称(rtable)。

对于分区表上的各种触发器,执行顺序如下:

表1 简单 INSERT 语句

顺序 目标表 TG_WHEN TG_OP TG_LEVEL TG_TABLE_NAME
1 分区表 BEFORE INSERT STATEMENT 分区表
2 分区 BEFORE INSERT ROW 分区
3 分区表 AFTER INSERT ROW 分区
4 分区 AFTER INSERT ROW 分区
5 分区表 AFTER INSERT STATEMENT 分区表

表 2 简单 UPDATE 语句(不存在跨分区移动数据)

扫描二维码关注公众号,回复: 4840666 查看本文章
顺序 目标表 TG_WHEN TG_OP TG_LEVEL TG_TABLE_NAME
1 分区表 BEFORE UPDATE STATEMENT 分区表
2 分区 BEFORE UPDATE ROW 分区
3 分区表 AFTER UPDATE ROW 分区
4 分区 AFTER UPDATE ROW 分区
5 分区表 AFTER UPDATE STATEMENT 分区表

表 3 简单 DELETE 语句

顺序 目标表 TG_WHEN TG_OP TG_LEVEL TG_TABLE_NAME
1 分区表 BEFORE DELETE STATEMENT 分区表
2 分区 BEFORE DELETE ROW 分区
3 分区表 AFTER DELETE ROW 分区
4 分区 AFTER DELETE ROW 分区
5 分区表 AFTER DELETE STATEMENT 分区表

表 4 TRUNCATE 语句

顺序 目标表 TG_WHEN TG_OP TG_LEVEL TG_TABLE_NAME
1 分区表 BEFORE TRUNCATE STATEMENT 分区表
2 分区 BEFORE TRUNCATE STATEMENT 分区
3 分区表 AFTER TRUNCATE STATEMENT 分区表
4 分区 BEFORE TRUNCATE STATEMENT 分区表

表 5 跨分区移动数据的 UPDATE 语句

顺序 目标表 TG_WHEN TG_OP TG_LEVEL TG_TABLE_NAME
1 分区表 BEFORE UPDATE STATEMENT 分区表
2 源分区 BEFORE UPDATE ROW 源分区
3 源分区 BEFORE DELETE ROW 源分区
4 目标分区 BEFORE INSERT ROW 目标分区
5 分区表 AFTER DELETE ROW 源分区表
6 源分区 AFTER DELETE ROW 源分区
7 分区表 AFTER INSERT ROW 目标分区
8 目标分区 AFTER INSERT ROW 目标分区
9 分区表 AFTER UPDATE STATEMENT 分区表

表 6 INSERT ON CONFLICT DO NOTHING(存在冲突)

顺序 目标表 TG_WHEN TG_OP TG_LEVEL TG_TABLE_NAME
1 分区表 BEFORE INSERT STATEMENT 分区表
2 分区 BEFORE INSERT ROW 分区
3 分区表 AFTER INSERT STATEMENT 分区表

另外,基于这种 AFTER 行级触发器,分区表还支持延迟的唯一约束。

官方文档:Table Partitioning

人生本来短暂,你又何必匆匆!点个赞再走吧!

猜你喜欢

转载自blog.csdn.net/horses/article/details/86085948