【问题标题】:Endless loop in trigger function触发功能中的无限循环
【发布时间】:2015-05-04 15:42:45
【问题描述】:

这是一个触发器,由对表的插入、更新或删除调用。保证调用表的所有列都受到影响,并且删除表也存在。

CREATE OR REPLACE FUNCTION sample_trigger_func() RETURNS TRIGGER AS $$
DECLARE
    operation_code char;
    table_name varchar(50);
    delete_table_name varchar(50);
    old_id integer; 

BEGIN
table_name = TG_TABLE_NAME;
delete_table_name = TG_TABLE_NAME || '_deletes';

SELECT SUBSTR(TG_OP, 1, 1)::CHAR INTO operation_code;

IF TG_OP = 'DELETE' THEN
    OLD.mod_op = operation_code;
    OLD.mod_date = now();

    RAISE INFO 'OLD: %', (OLD).name;

    EXECUTE format('INSERT INTO %s VALUES %s', delete_table_name, (OLD).*);

ELSE
    EXECUTE format('UPDATE TABLE %s SET mod_op = %s AND mod_date = %s'
                  , TG_TABLE_NAME, operation_code, now());
END IF;

RETURN NEW;
END;

$$ LANGUAGE plpgsql;

ELSE 分支触发无限循环。可能还有更多问题。 如何解决?

【问题讨论】:

  • 我投票决定将此问题作为离题结束,因为没有问题陈述,而且看起来 OP 要求进行代码审查。这个问题可能是codereview.stackexchange.com 的主题。
  • @Kevin:你说得对,我添加了 OP 忘记的问题陈述。从上一个问题我可以看出。

标签: postgresql triggers plpgsql postgresql-9.1


【解决方案1】:

ELSE 分支可以从根本上简化。但是还有一些事情是低效/不准确/危险的:

CREATE OR REPLACE FUNCTION sample_trigger_func()
  RETURNS TRIGGER AS
$func$
BEGIN
   IF TG_OP = 'DELETE' THEN
      RAISE INFO 'OLD: %', OLD.name;

      EXECUTE format('INSERT INTO %I SELECT ($1).*', TG_TABLE_NAME || '_deletes')
      USING OLD #= hstore('{mod_op, mod_datetime}'::text[]
                         , ARRAY[left(TG_OP, 1), now()::text]);
      RETURN OLD;
   ELSE  -- insert, update
      NEW.mod_op       := left(TG_OP, 1);
      NEW.mod_datetime := now();

      RETURN NEW;
   END IF;
END
$func$  LANGUAGE plpgsql;

我在使用它的同时还添加了一些其他改进。触发器本身应该是这样的:

CREATE TRIGGER insupdel_bef
BEFORE INSERT OR UPDATE OR DELETE ON table_name
FOR EACH ROW EXECUTE PROCEDURE sample_trigger_func();

SQL Fiddle.

【讨论】:

  • Erwin,我仍然没有使用 mod_op 和 mod_dates 更新插入和更新。你知道这是为什么吗?我的设置有什么问题吗?
  • @picmate:你见过小提琴吗?有用。我已经多次使用类似的技术。对于同一张桌子上的同一事件,您是否有其他可能会干扰的触发器?还是意外硬编码表名?或者你没有得到CREATE TRIGGER 对吗?我将其添加到答案中。另请注意:mod_datetime!我添加了一条注释。
  • 谢谢欧文。这太棒了。问题是在初始化触发器之后。将其更改为以前,现在可以正常工作。不幸的是,我无法将额外的模块添加到生产环境(代码最终会去的地方)。因此,不得不避免使用hstore。但是,从您的回答中对这个过程有了很多了解。
  • @picmate; hstore 就是这么一个基本的、强大的模块,真的应该大部分时间都安装...
  • 我一定会检查,如果没有安装建议我们的操作人员。如果他们同意我的意见,他们将进行添加,这将使我保留您建议的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多