版权声明:本站不全为博主原创文章,欢迎转载,转载记得标明出处。^-^ 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 语句(不存在跨分区移动数据)
顺序 | 目标表 | 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
人生本来短暂,你又何必匆匆!点个赞再走吧!