我正在尝试实现表分区,我在 PostgreSQL 中有以下代码(来自 https://www.postgresql.org/docs/9.6/ddl-partitioning.html)
CREATE or replace FUNCTION child_tables.func_inventory_movement_insert_trigger()
RETURNS trigger
LANGUAGE 'plpgsql'
COST 100
VOLATILE NOT LEAKPROOF
AS $BODY$BEGIN
IF ( NEW.report_date >= '2019-04-01 ' AND
NEW.report_date < '2019-05-01 ' ) THEN
INSERT INTO child_tables.inventory_movement_y2019m03 VALUES (NEW.*);
ELSIF ( NEW.report_date >= '2019-06-01 ' AND
NEW.report_date < '2019-07-01 ' ) THEN
INSERT INTO child_tables.inventory_movement_y2019m04 VALUES (NEW.*);
ELSE
RAISE EXCEPTION
' out of range exception. Fix the child_tables.func_inventory_movement_insert_trigger() function. ';
END IF;
RETURN NULL;
END;
$BODY$;
触发函数:
CREATE TRIGGER im_partition_trigger
BEFORE INSERT OR DELETE OR UPDATE
ON core.inventory_movement
FOR EACH ROW
EXECUTE PROCEDURE child_tables.func_inventory_movement_insert_trigger();
在上述触发器之后或之前都进行了尝试。
ERROR: record "new" is not assigned yet DETAIL: The tuple structure of a not-yet-assigned record is indeterminate.
仅供引用,相同的代码适用于另一个表。
有什么建议吗?
最佳答案
你的触发器已定义
BEFORE INSERT OR DELETE OR UPDATE
但是 NEW
没有为 DELETE
定义。所以你的触发函数注定会失败。
要么为INSERT
/UPDATE
/DELETE
编写单独的触发器函数和触发器(推荐)。显示的触发器函数仅处理 INSERT
。所以这个触发器是有意义的:
CREATE TRIGGER im_partition_trigger
BEFORE INSERT -- !!
ON core.inventory_movement
FOR EACH ROW EXECUTE PROCEDURE child_tables.func_inventory_movement_insert_trigger();
或者将所有对 OLD
和 NEW
的调用嵌套在 IF
或 CASE
结构中的组合触发器函数中,检查对于 TG_OP
.
Code examples in many related questions.
也就是说,要实现表分区,我更愿意使用 declarative partitioning在 Postgres 10 或更高版本中。理想情况下,使用即将推出的 Postgres 12,它为分区带来了重大改进。
此外,在 Postgres 11 或更高版本中,触发器使用固定语法:
...
FOR EACH ROW EXECUTE FUNCTION child_tables.func_inventory_movement_insert_trigger();
这是一个函数,而不是一个“过程”。
关于postgresql - 记录 "new"尚未分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58020214/