我有两张 table
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';
发生错误:
ERROR: stack depth limit exceeded
HINT: Increase the configuration parameter "max_stack_depth" (currently 2048kB), after ensuring the platform's stack depth limit is adequate.
最佳答案
有几种方法可以防止您在触发器中内置的无限递归,最优雅和高效的可能是添加一个 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();
我改变了一些其他的东西来走向理智:
由于触发器函数对每一行都执行相同的操作,因此我将其更改为可能便宜得多 statement-level trigger .
因此,我制作了触发函数
RETURN NULL
,因为,I quote the manual here :
Trigger functions invoked by per-statement triggers should always return NULL.
batch.is_locked
和sem.is_active
看起来像 bool 列。使用适当的boolean
data type为他们。我的代码以此为基础。我还重写了你的
UPDATE
查询完全。特别是batch.start_date
上的条件以便在可用时使用索引。如果
batch.is_locked
定义NOT NULL
,WHERE
条件可以简化为:AND b.is_locked = FALSE;
关于postgresql - 更新后使用触发器更新表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14137932/