postgresql Postgres语句级触发器错误:不能为具有列列表的触发器指定转换表

5lwkijsr  于 2022-12-18  发布在  PostgreSQL
关注(0)|答案(1)|浏览(222)

我有一个列为 id 的表 my_table(整数),* 值 *(瓦尔查尔),和 * 修改 *(时间戳)。我希望在每次设置新值时通过触发器更新时间戳。我在一个查询中更改数千行,因此不希望使用行级触发器(aka FOR EACH ROW),并在一次调用中修改整个更新集,而不是每一行的数千个。

CREATE TRIGGER my_trigger
AFTER UPDATE OF value
ON my_schema.my_table
REFERENCING NEW TABLE AS updated OLD TABLE AS prev
FOR EACH STATEMENT
EXECUTE PROCEDURE my_schema.my_trigger_function()

我在创建过程中遇到错误:
[0A000]错误:不能为具有列列表的触发器指定转换表
如果我删除了“REFERENCING NEW TABLE AS updated OLD TABLE AS prev”,那么我如何访问更新的数据集?如果我删除了“OF value”部分,那么我将获得递归触发器调用,因为触发器会通过更改同一个表但不同的列来再次激发自己。因此,我想到的最佳解决方案是's来消除IF条件的第二次递归调用:

CREATE TRIGGER my_trigger
AFTER UPDATE
ON my_schema.my_table
REFERENCING NEW TABLE AS updated OLD TABLE AS prev
FOR EACH STATEMENT
EXECUTE PROCEDURE my_schema.my_trigger_function()

CREATE OR REPLACE FUNCTION my_schema.my_trigger_function()
    RETURNS TRIGGER
    LANGUAGE PLPGSQL
AS
$$
BEGIN

    IF EXISTS(SELECT 1
               FROM updated
                        INNER JOIN prev ON updated.modified = prev.modified) THEN
        UPDATE my_schema.my_table
        SET modified = NOW()
        WHERE id IN (SELECT id FROM updated);
    END IF;

    RETURN NULL;
END;
$$;

如果我知道如何使用“AFTER UPDATE OF value”访问所有更新的行,而不使用 updatedprev,我会做得更好,这就是我在这里的原因。

vwkv1x7d

vwkv1x7d1#

您可以通过在声明中添加WHEN (PG_TRIGGER_DEPTH() = 0)来避免触发器的递归调用:

CREATE TRIGGER my_trigger
AFTER UPDATE ON my_schema.my_table
REFERENCING NEW TABLE AS updated OLD TABLE AS prev
FOR EACH STATEMENT
WHEN (PG_TRIGGER_DEPTH() = 0)
EXECUTE PROCEDURE my_schema.my_trigger_function()

相关问题