0

我正在尝试实现表分区,我在 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.

仅供参考,相同的代码适用于另一张桌子。

有什么建议么?

4

1 回答 1

3

您的触发器已定义

BEFORE INSERT OR DELETE OR UPDATE 

NEW不是为 a 定义的DELETE。因此,您的触发功能肯定会像以前那样失败。

INSERT要么为//编写单独的触发函数和触发器UPDATEDELETE推荐)。显示的触发功能只处理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和的调用嵌套NEWIForCASE构造中的组合触发器函数中,检查TG_OP.

许多相关问题中的代码示例。

也就是说,为了实现表分区,我更愿意在 Postgres 10 或更高版本中使用声明式分区。理想情况下,使用即将推出的 Postgres 12,它为分区带来了很大的改进。

另外,在 Postgres 11 或更高版本中,不如使用触发器的固定语法:

...
FOR EACH ROW EXECUTE FUNCTION child_tables.func_inventory_movement_insert_trigger();

这是一个功能,而不是一个“程序”。

于 2019-09-20T02:18:54.807 回答