PostgreSQL 9.3 触发函数以参数化名称插入表

Posted

技术标签:

【中文标题】PostgreSQL 9.3 触发函数以参数化名称插入表【英文标题】:PostgreSQL 9.3 trigger function to insert into table with parameterized name 【发布时间】:2014-06-08 10:50:43 【问题描述】:

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

我使用INSERT INTO log5 VALUES (NEW.*) 运行该函数,它可以工作。

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

错误:

查询:插入 log5 值(新。*) 上下文:PL/pgSQL 函数 log_roll_test() 第 6 行在 EXECUTE 语句 错误:缺少表“新”SQL 状态的 FROM 子句条目: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();

【问题讨论】:

NEW 无法识别,因为EXECUTE 无法引用外部变量。尝试使用USING 子句。 postgresql.org/docs/9.3/static/… 谢谢!我已经尝试过了,但它不起作用。它将 NEW 记录传递给语句,而 EXECUTE 语句将其视为字符串。即'(value1, value2, value3,,,)'。 Postgres 不喜欢将逗号放在一起,也不喜欢在值周围加上引号。我需要做一个 regexp_replace 来修改字符串,出于性能原因,我真的很想避免这种情况。 我什么都试过了,顺便说一句。非常接近于放弃并使用 CASE WHEN 语句(53 行)编写触发器并编写 pgScript 来创建 53 个单独的触发器函数。 【参考方案1】:
CREATE FUNCTION log_roll_test()
  RETURNS trigger 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$ LANGUAGE plpgsql;

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

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

【讨论】:

谢谢欧文!!!简单而优雅的解决方案。我将在 format() 语句中使用 %I.%I 以便添加模式限定符。它工作得很好,将使触发器功能适用于多个日志表。 @DavidWillis:模式名称从何而来?对于静态值%s 就足够了。 %I 仅用于清理动态值。如果架构和表名是动态的,a cast to regclass would be an alternative。 Another related answer here. 良好的链接。架构名称是静态的。我最终将 tg_table_name 转换为 regclass。目标是让一个简单的触发器函数适用于多个日志表,我想我就在那里。感谢您的帮助!

以上是关于PostgreSQL 9.3 触发函数以参数化名称插入表的主要内容,如果未能解决你的问题,请参考以下文章

错误:使用 PostgreSQL 9.3 的 dblink 中的函数需要列定义列表

jmeter的日常特殊参数化

jmeter的日常特殊参数化

将 Excel 数据导入 PostgreSQL 9.3

PostgreSQL - 如何将函数的参数传递给触发器?

“名称”类型的 PostgreSQL 函数参数存在问题