Postgresql触发器在NEW和OLD记录上运行

时间:2018-03-29 19:51:56

标签: postgresql triggers plpgsql

这主要是一个风格问题。

我有一个AFTER INSERT或UPDATE触发器。我想针对可用的新/旧记录中的任何一个运行相同查询。而不是让条件检查TG_OP并复制查询,有什么最简单的方法来确定哪些可用并循环它们?

示例代码:

CREATE FUNCTION myfunc() RETURNS TRIGGER AS $$
  DECLARE
    id int;
    ids int[];
  BEGIN
    IF TG_OP IN ('INSERT', 'UPDATE') THEN
      ids := ids || NEW.id;
    END IF;

    IF TG_OP IN ('UPDATE', 'DELETE') THEN
      ids := ids || OLD.id;
    END IF;

    FOREACH id IN ARRAY ARRAY(SELECT DISTINCT UNNEST(ids))
    LOOP
      RAISE NOTICE 'myfunc called for % on id %', TG_OP, id;
      /* RUN QUERY REFERENCING id */
    END LOOP;

    RETURN NULL;
  END;
$$ LANGUAGE plpgsql;

是否有更短/更简单/更惯用的方法来实现这一目标?

1 个答案:

答案 0 :(得分:1)

数组处理和单独的SELECT DISTINCT似乎对于这项工作而言过于昂贵。这应该更便宜:

CREATE FUNCTION myfunc()
  RETURNS TRIGGER AS
$func$
DECLARE
   _id int;
BEGIN
   CASE TG_OP
      WHEN 'INSERT', 'UPDATE' THEN
         _id := NEW.id;
      WHEN 'DELETE' THEN
         _id := OLD.id;
   END CASE;

   FOR i IN 1..2  -- max 2 iterations
   LOOP
      RAISE NOTICE 'myfunc called for % on id %', TG_OP, _id;
      /* RUN QUERY REFERENCING _id */

      EXIT WHEN TG_OP <> 'UPDATE' OR i = 2;  -- only continue in 1st round for UPDATE  
      EXIT WHEN _id = OLD.id;                -- only continue for different value
      _id := OLD.id;
   END LOOP;
   RETURN NULL;
END
$func$  LANGUAGE plpgsql;

相关:

但我可能只是写一个单独的触发功能&amp;触发每个DML语句。而不是一个非常简单和快速的功能,而不是一个通用但复杂和较慢的功能。