触发触发器时超出堆栈深度限制
Posted
技术标签:
【中文标题】触发触发器时超出堆栈深度限制【英文标题】:stack depth limit exceeded when fired a trigger 【发布时间】:2019-06-20 17:45:09 【问题描述】:我正在尝试构建一个缓慢变化的维度表,它跟踪所有记录的历史记录。表的架构是这样的:
CREATE TABLE test.dim
(id text,
column1 text,
column2 text,
begin_date timestamp without time zone,
is_current boolean,
end_date timestamp without time zone)
我定义了一个触发函数,并在每个插入操作之前触发它:
CREATE OR REPLACE FUNCTION test.slow_change_func()
RETURNS trigger AS
$BODY$
DECLARE
BEGIN
IF ( NOT EXISTS ( SELECT 1 FROM yang_test.dim
WHERE id= NEW.id
AND(column1 = NEW.column1 OR (column1 is null AND NEW.column1 is null))
AND (column2 = NEW.column2 OR (column2 is null AND NEW.column2 is null))
AND is_current
)
)
THEN UPDATE yang_test.dim
SET (end_date, is_current) = (now(), FALSE)
WHERE id = NEW.id
AND is_current;
INSERT INTO test.dim (id, column1, column2, begin_date, is_current, end_date)
VALUES ( NEW.id, NEW.column1, NEW.column2, now(), TRUE, 'infinity'::timestamp );
END IF;
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
CREATE TRIGGER slow_change_trigger
BEFORE INSERT
ON test.dim
FOR EACH ROW
EXECUTE PROCEDURE test.slow_change_func();
当我尝试测试它时,
INSERT INTO test.dim (id, column1, column2, begin_date, is_current, end_date)
VALUES ( 1, 'hello', 'world', now(), TRUE, 'infinity'::timestamp )
它会抛出一个错误:超出堆栈深度限制。看起来该函数正在循环运行。有什么建议吗?
【问题讨论】:
您的插入触发器插入到数据库中,因此它将被一遍又一遍地触发。它似乎使用与第一个插入的值相同的值。真的是你的意思吗? 感谢您的解释。如何预防?我当然只想在插入语句之前触发一次触发函数。谢谢 如果你删除了触发器内的插入,它不应该发生。但是它存在有什么原因,比如您想在某些情况下取消插入? 我不希望每一行都插入到表中。如果新行已经在表中(相同的 id、column1、column2 值),则什么也不做;否则,更新表中的旧行并插入新行。 【参考方案1】:我想我已经弄清楚了,这将符合我的要求:
CREATE OR REPLACE FUNCTION yang_test.slow_change_func()
RETURNS trigger AS
$BODY$
DECLARE
BEGIN
IF ( NOT EXISTS ( SELECT 1 FROM yang_test.dim
WHERE id= NEW.id
AND(column1 = NEW.column1 OR (column1 is null AND NEW.column1 is null))
AND (column2 = NEW.column2 OR (column2 is null AND NEW.column2 is null))
AND is_current
)
)
THEN UPDATE yang_test.dim
SET (end_date, is_current) = (now(), FALSE)
WHERE id = NEW.id
AND is_current;
ELSE RETURN null;
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
【讨论】:
以上是关于触发触发器时超出堆栈深度限制的主要内容,如果未能解决你的问题,请参考以下文章