PostgreSQL 9.3 触发器函数插入到具有参数化名称的表中

标签 postgresql triggers plpgsql dynamic-sql

我正在尝试动态分区 Postgres 中的日志条目。我有 53 个子表(每周 1 个用于日志条目),并且想使用触发器将 INSERT 路由到子表。

我使用 INSERT INTO log5 VALUES (NEW.*) 运行该函数,它有效。

我改为使用 EXECUTE 语句运行该函数,但它失败了。在 EXECUTE 语句中,它将 NEW 识别为表名,而不是传递给触发器函数的变量。关于如何修复的任何想法?谢谢!

错误:

QUERY: INSERT INTO log5 VALUES (NEW.*)
CONTEXT: PL/pgSQL function log_roll_test() line 6 at EXECUTE statement
ERROR: missing FROM-clause entry for table "new" SQL state: 42P01

我的函数:

CREATE FUNCTION log_roll_test() RETURNS trigger AS $body$
DECLARE t text;
BEGIN
    t := 'log' || extract(week FROM NEW.updt_ts); --child table name
    --INSERT INTO log5 VALUES (NEW.*);
    EXECUTE format('INSERT INTO %I VALUES (NEW.*);', t);
    RETURN NULL;
END;
$body$ LANGUAGE plpgsql;

我的触发器:

CREATE TRIGGER log_roll_test
BEFORE INSERT ON log FOR EACH ROW
EXECUTE PROCEDURE log_roll_test();

最佳答案

CREATE FUNCTION log_roll_test()
  RETURNS trigger
  LANGUAGE plpgsql AS
$func$
BEGIN
   EXECUTE format('INSERT INTO %I SELECT ($1).*'     -- !
                , to_char(NEW.updt_ts, '"log"WW'))   -- child table name
   USING NEW;  -- !
   RETURN NULL;
END
$func$;

您不能在查询字符串中引用 NEWNEW 在函数体中可见,但在 EXECUTE 环境中不可见。最好的解决方案是在 USING 子句中传递值。

我还用等效的 to_char(NEW.updt_ts, '"log"WW') 替换了表名。 to_char()在这里更快更简单。

关于PostgreSQL 9.3 触发器函数插入到具有参数化名称的表中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23247105/

相关文章:

postgresql - Postgres COPY TO PROGRAM 使用动态命令

c# - 如何使用 Entity Framework Core 3.0 创建所需的拥有类型

sql - 使用 PostgreSQL 在所有 JSON 字段中搜索

插入新行后mysql触发器table1复制到table2选定的字段而不重复

mysql - 如何选择触发器(mysql)中声明的变量?

mysql - 如何使用Sql触发器列出表中的所有列

postgresql - 安全定义器不在内部工作而不是触发器?

postgresql - 尝试在 PostgreSQL 中创建聚合函数

sql - 重构字段的外键

postgresql - 如何从 plpgsql 函数中获取结果