【问题标题】:Can I iterate over NEW in a PostgreSQL trigger function?我可以在 PostgreSQL 触发器函数中迭代 NEW 吗?
【发布时间】:2015-06-15 06:43:55
【问题描述】:

我编写了一个触发器函数,希望遍历 NEW 并检查其所有值。

CREATE OR REPLACE FUNCTION fix_nulls() RETURNS TRIGGER AS $_$
BEGIN
    FOR val IN NEW
    LOOP
        IF val = '{x:Null}'
            val := '';
        ENDIF;      
    ENDLOOP;
    RETURN NEW;
END $_$ LANGUAGE 'plpgsql';

CREATE TRIGGER prevent_nulls_siteinfo
    BEFORE UPDATE OR INSERT ON siteinfo
    FOR EACH ROW
    EXECUTE PROCEDURE fix_nulls();

但我得到一个语法错误:

ERROR:  syntax error at or near "NEW"
LINE 3:  FOR val IN NEW
                    ^

是否可以遍历NEW 中的所有值?我可以很容易地编写一堆 if 语句来检查每一列,但我希望这个函数是通用的,这样我以后可以将它用于其他表。

【问题讨论】:

标签: postgresql triggers plpgsql dynamic-sql


【解决方案1】:

简单案例的静态代码

对于一堆给定的列,我会拼出来。

CREATE OR REPLACE FUNCTION fix_nulls()
  RETURNS TRIGGER AS
$func$
BEGIN
   IF NEW.val1 = '{x:Null}' THEN NEW.val1 := ''; END IF;
   IF NEW.val2 = '{x:Null}' THEN NEW.val2 := ''; END IF;
   IF NEW.va31 = '{x:Null}' THEN NEW.val3 := ''; END IF;

   RETURN NEW;
END
$func$  LANGUAGE plpgsql;
  • 不要引用语言名称plpgsql,它是一个标识符。

并且仅在相关时触发触发器:

CREATE TRIGGER prevent_nulls_siteinfo
BEFORE UPDATE OR INSERT ON siteinfo
FOR EACH ROW 
WHEN ('{x:Null}' IN (NEW.val1, NEW.val2, NEW.val3))
EXECUTE PROCEDURE fix_nulls();

动态代码

如果有 许多 列或(更好的原因)列(名称)变化很大,则可能需要采用动态方法。然而,虽然 plpgsql FOR 循环可以迭代集合(表)中的行数组中的元素,但它可以 对一行中的列执行相同操作。
为什么?

【讨论】:

  • 这很棒!我必须对触发器进行一个小改动:FOR 必须位于 WHEN 之前,EXECUTE PROCEDURE 位于后面。
  • @raddevon:好的,谢谢,已修复。这与我花哨的格式混淆了。
猜你喜欢
  • 2018-11-30
  • 2021-05-23
  • 1970-01-01
  • 2018-07-15
  • 2021-05-23
  • 1970-01-01
  • 2013-11-05
  • 1970-01-01
  • 2011-03-26
相关资源
最近更新 更多