通过 Postgres 触发器中的键分配给 NEW

Ben*_*Ben 5 postgresql trigger plpgsql functions

在触发器主体中,如何NEW通过其字段名称为其分配值?
这就是我想要做的:

some_key = "some_column";
NEW[some_key] = 5;
Run Code Online (Sandbox Code Playgroud)

Erw*_*ter 14

首先,有没有“触发体”(不像甲骨文)。在 Postgres 中,您有一个带有函数主体的触发器函数(也被误导地称为“过程”)和调用此函数的 0-n 触发器(没有主体)。

NEWplpgsql 触发器函数中的特殊变量既不是映射也不是数组;这是保存新行的记录

NEW

数据类型RECORD;在行级触发器中保存INSERT/UPDATE操作的新数据库行的变量 。此变量在语句级触发器和DELETE操作中未分配。

分配给字段(或列)的NEW很简单。记录的赋值运算符是:=. (也从 Postgres 9.4 开始=

NEW.some_key := 5;
Run Code Online (Sandbox Code Playgroud)

您似乎正在寻找的是参数化列 name,这并不那么简单。
附加模块hstore提供了#=操作者。(它几乎包含在所有标准发行版中。)为每个数据库安装一次模块:

CREATE EXTENSION hstore;
Run Code Online (Sandbox Code Playgroud)

然后你可以:

NEW := NEW #= '"some_key"=>"5"'::hstore;
Run Code Online (Sandbox Code Playgroud)

将列设置some_key为 '5' - 如果该列存在。

  • 显式强制转换hstore为可选。该运算符#=自动将字符串文字强制为正确的数据类型。
  • hstore仅存储文本字符串,因此值的给定文字可能必须转换两次- 与替代解决方案相比,这是一个非常小的缺点。
  • 给定的字符串文字必须适合列的数据类型,否则会引发异常。
  • 如果不存在具有给定名称的列,则不会发生任何更改,也不会引发异常。

有关详细信息和替代解决方案的相关答案:

代码示例

CREATE OR REPLACE FUNCTION trg_tbl_ins_bef()
  RETURNS trigger AS
$func$
BEGIN
   NEW := NEW #= '"some_key"=>"5"';
   RETURN NEW;
END
$func$ LANGUAGE plpgsql;

CREATE TRIGGER ins_bef
BEFORE INSERT ON tbl
FOR EACH ROW EXECUTE PROCEDURE trg_tbl_ins_bef();
Run Code Online (Sandbox Code Playgroud)

Postgres 11 或更高版本允许替换误导性术语PROCEDURE(旧语法将在可预见的未来继续工作):

...
FOR EACH ROW EXECUTE FUNCTION trg_tbl_ins_bef();
Run Code Online (Sandbox Code Playgroud)

  • 查看链接的答案。在引入“#=”运算符之前,帕维尔和我努力寻找解决方案 - 并且也找到了一个。 (2认同)