更新表更新后触发(Update a table with a trigger after updat

2019-08-05 10:32发布

我有两个表

 batch (batch_id,start_date,end_date,batch_strength,is_locked)
 sem (user_id,is_active,no_of_days)

我已经执行下面再给予触发器过程使用查询更新表

CREATE OR REPLACE FUNCTION em_batch_update()
  RETURNS trigger AS $em_sem_batch$
BEGIN

UPDATE batch set is_locked='TRUE'
where (start_date
       + (select no_of_days from sem
          WHERE is_active='TRUE' and user_id='OSEM')
      ) <= current_date;

return NEW;

END;
$em_sem_batch$  LANGUAGE plpgsql;

CREATE TRIGGER em_sem_batch
BEFORE UPDATE ON batch FOR EACH ROW EXECUTE PROCEDURE em_batch_update();

update em_batch set batch_strength=20 where batch_id='OD001C001B3';

发生了错误:

错误:堆栈深度超出限制
提示:增加配置参数“max_stack_depth”(目前2048KB),保证了平台的堆栈深度限制是足够的了。

Answer 1:

有几种方法可以防止你内置到触发的无限递归 ,最优雅的和高性能的可能增加一个WHERE子句的UPDATE在你的触发功能的语句:

CREATE OR REPLACE FUNCTION em_batch_update()
  RETURNS trigger AS
$func$
BEGIN

UPDATE batch b
SET    is_locked = TRUE
FROM   sem s
WHERE  s.is_active
AND    s.user_id = 'OSEM'
AND    b.start_date <= (current_date - s.no_of_days)
AND    b.is_locked IS DISTINCT FROM TRUE; -- prevent infinite recursion!

RETURN NULL;

END
$func$  LANGUAGE plpgsql;

CREATE TRIGGER em_sem_batch
BEFORE UPDATE ON batch
FOR EACH STATEMENT
EXECUTE PROCEDURE em_batch_update();

我改变了一些其他的东西走向理智移动:

  • 由于触发功能做同样的每一行,我把它改为一个潜在的便宜得多 语句级触发器 。

  • 因此,我所做的触发功能RETURN NULL ,因为, 我在这里引用手册 :

按语句触发的触发器应该总是返回NULL。

  • batch.is_lockedsem.is_active样子布尔列。 使用合适的boolean数据类型为他们。 我的代码是建立在其上。

  • 我还改写了你的UPDATE完全查询。 特别是在条件batch.start_date使得索引可以(如果可用)。

  • 如果batch.is_locked定义NOT NULL ,则WHERE条件可以被简化为:

      AND b.is_locked = FALSE; 


Answer 2:

UPDATE触发器运行另一个UPDATE同一个表,这将再次触发触发器,所以你得到无限递归。 你可能需要重新设计这一点,但很难说有没有你正在试图做什么解释。



Answer 3:

在这种情况下,因为更新触发器会做表的更新操作无限递归batch和相同的内部就会更新语句执行后触发em_sem_batch触发itself.To防止这种情况表,并在触发更新的更新语句添加一列该列也在一定值,并添加一个if条件检查列是否有固定值,如果这样就可以避免更新语句的执行其他执行更新语句。 见下面例子:

CREATE FUNCTION public.trigger_fuction()
    RETURNS trigger
    LANGUAGE 'plpgsql'
    NOT LEAKPROOF
AS $BODY$
BEGIN
  IF NEW.data_replicated=true THEN
    UPDATE sample SET data_replicated=false WHERE id=NEW.id;
    raise notice 'changed data replicated of sample with id as %',NEW.ID;
  END IF;
  RETURN NEW;
END;
$BODY$;


CREATE TRIGGER data_replication_trigger
  AFTER UPDATE
  ON sample
  FOR EACH ROW
  EXECUTE PROCEDURE trigger_fuction();

在这个例子中试样台已data_replicated执行触发时将被更新的布尔字段。



文章来源: Update a table with a trigger after update