我有两个表
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),保证了平台的堆栈深度限制是足够的了。
有几种方法可以防止你内置到触发的无限递归 ,最优雅的和高性能的可能增加一个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();
我改变了一些其他的东西走向理智移动:
按语句触发的触发器应该总是返回NULL。
batch.is_locked
和sem.is_active
样子布尔列。 使用合适的boolean
数据类型为他们。 我的代码是建立在其上。
我还改写了你的UPDATE
完全查询。 特别是在条件batch.start_date
使得索引可以(如果可用)。
如果batch.is_locked
定义NOT NULL
,则WHERE
条件可以被简化为:
AND b.is_locked = FALSE;
你UPDATE
触发器运行另一个UPDATE
同一个表,这将再次触发触发器,所以你得到无限递归。 你可能需要重新设计这一点,但很难说有没有你正在试图做什么解释。
在这种情况下,因为更新触发器会做表的更新操作无限递归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执行触发时将被更新的布尔字段。