如何创建一个 Postgres 11 触发器函数,该函数在插入或更新到表“a”时在表“b”中插入一个新行?

Posted

技术标签:

【中文标题】如何创建一个 Postgres 11 触发器函数,该函数在插入或更新到表“a”时在表“b”中插入一个新行?【英文标题】:How can I create a Postgres 11 trigger function which inserts a new row in table 'b' upon insert or update to table 'a'? 【发布时间】:2021-02-03 23:49:48 【问题描述】:

我在 RDS 上运行 Postgres 11。 我正在尝试创建一个简单的触发器函数,以便在将行插入表“test_values”时将记录插入表“test_alias”。

我有以下表格:

CREATE TABLE the_schema.test_values (
    id INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT now(), 
    value_1 TEXT NOT NULL, 
    value_2 TEXT NOT NULL,
    value_quantity INTEGER NOT NULL
);

CREATE TABLE the_schema.test_alias (
    id INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT now(), 
    value_1_copy TEXT NOT NULL, 
    value_2_copy TEXT NOT NULL,
    value_quantity_copy INTEGER NOT NULL
);

我的触发函数是这样的:

CREATE OR REPLACE FUNCTION the_schema.populate_test_alias()
RETURNS TRIGGER AS
$BODY$
BEGIN
IF NEW.the_schema.test_values THEN 
INSERT INTO the_schema.test_alias (value_1_copy, value_2_copy, value_quantity_copy)
VALUES (NEW.value_1, NEW.value_2, NEW.value_quantity);
END IF;
return null;
END; 
$BODY$ LANGUAGE plpgsql;

这里是触发器:

CREATE TRIGGER TRG_TEST_ALIAS 
AFTER INSERT OR UPDATE ON the_schema.test_values
FOR EACH ROW 
execute procedure the_schema.populate_test_alias();

像这样插入:

INSERT INTO the_schema.test_values (value_1, value_2, value_quantity)
VALUES ('abc', 'xyz', 1);

我收到此错误:

ERROR:  missing FROM-clause entry for table "the_schema"
LINE 1: SELECT NEW.the_schema.test_values

我还尝试了使用默认架构的等效设置,但它仍然出错(尽管有不同的错误):

ERROR:  record "new" has no field "test_values"
CONTEXT:  SQL statement "SELECT NEW.test_values"
PL/pgSQL function populate_test_alias() line 3 at IF

在我看来,我使用 NEW 关键字的方式一定有错误,但据我所知,我在函数中使用它的方式与我的几个示例相同'已经提到(在线/SO 和硬拷贝),我想不通。

非常感谢所有指导!


类似问题的示例供参考,包括官方文档的链接(我也读过,但显然不明白我应该理解): [https://***.com/questions/11001118/postgres-trigger-after-insert-accessing-new]

【问题讨论】:

这个IF NEW.the_schema.test_values THEN 应该测试什么? NEW 引用插入的行。 好问题!我从教程中复制了它,但现在你提到它,它似乎是多余的——让我尝试不使用条件——编辑:删除if 语句后,我收到以下错误:ERROR: record "new" has no field "test_values" CONTEXT: SQL statement "SELECT NEW.test_values" PL/pgSQL function populate_test_alias() line 3 at IF 删除整行 - 显然还有 END iF。 很好,成功了!感谢您的帮助,我非常感谢! 【参考方案1】:

NEW 引用插入或更新的行。因此NEW. 只对字段标识符有意义。

还有value_1, value_2value_quantity 有一个NOT NULL 约束,这意味着您不需要测试它们。

所以你可以放弃整个条件:

CREATE OR REPLACE FUNCTION the_schema.populate_test_alias()
RETURNS TRIGGER AS
$BODY$
BEGIN
--IF NEW.the_schema.test_values THEN 
INSERT INTO the_schema.test_alias (value_1_copy, value_2_copy, value_quantity_copy)
VALUES (NEW.value_1, NEW.value_2, NEW.value_quantity);
--END IF;
return null;
END; 
$BODY$ LANGUAGE plpgsql;

【讨论】:

以上是关于如何创建一个 Postgres 11 触发器函数,该函数在插入或更新到表“a”时在表“b”中插入一个新行?的主要内容,如果未能解决你的问题,请参考以下文章

这个 postgres 触发函数有啥问题?

postgres 触发器创建索引:BEFORE INSERT ON 隐藏一行

在 Postgres 上使用 pl/Python 创建触发器

如何使用 Postgres 和 GraphQL 在特定日期自动触发事件?

使用 postgres 构建一个触发器函数来处理 json 数据

创建或替换触发器 postgres