触发提升:“错误:超出堆栈深度限制”

我试图在插入绘画后将其插入In_Gallery表或On_Loan表中,但不能同时插入其中。当我尝试制作触发函数时,我不断收到错误消息:

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.

我不确定这是怎么回事:

    CREATE OR REPLACE FUNCTION checkOnLoan()    
    RETURNS trigger AS
$$
    DeclARE    
       countGal numeric;
    BEGIN
            SELECT COUNT(*) INTO countGal FROM IN_GALLERY WHERE P_id = new.P_id;
            IF countGal = 0 THEN    
                INSERT INTO ON_LOAN VALUES (new.Certid,new.P_id,new.Insurer);
            ELSE
                RAISE EXCEPTION 'ALREADY IN GALLERY';
            END IF;
    RETURN new;
    END;
$$

LANGUAGE 'plpgsql';

CREATE TRIGGER OnLoan
    AFTER INSERT ON ON_LOAN
    FOR EACH ROW
    EXECUTE PROCEDURE checkOnLoan();
deronglpo 回答:触发提升:“错误:超出堆栈深度限制”

您在INSERT触发器中再次AFTER INSERT,导致在第二个INSERT再次触发该触发器,而该INSERT又触发并重新触发该触发器,依此类推等等。在某些时候,所有的函数调用都会耗尽堆栈,您会得到错误。

从触发功能中删除INSERT,仅删除RETURN new。返回new将使原始INSERT完成。无需手动使用INSERT触发器的AFTER INSERT触发器功能。

赞:

CREATE OR REPLACE FUNCTION checkOnLoan()    
RETURNS trigger AS
$$
DECLARE    
    countGal numeric;
BEGIN
    SELECT COUNT(*) INTO countGal FROM IN_GALLERY WHERE P_id = new.P_id;
    IF countGal = 0 THEN    
        RETURN new;
    ELSE
        RAISE EXCEPTION 'ALREADY IN GALLERY';
    END IF;
END;
$$
LANGUAGE plpgsql;

和其他触发功能的模拟信号。

,

直接导致您出错的原因是一个无休止的循环,就像当前接受的答案一样。但是,您可能不仅应该解决此问题。 BEFORE触发器将改善情况……

触发功能:

CREATE OR REPLACE FUNCTION check_onloan()
  RETURNS trigger AS
$$
BEGIN
   IF EXISTS (SELECT FROM in_gallery WHERE p_id = NEW.p_id) THEN
      RAISE EXCEPTION 'p_id % already in gallery!',NEW.p_id;
   END IF;
   RETURN NEW;  -- for BEFORE trigger
END
$$  LANGUAGE plpgsql;

触发:

CREATE TRIGGER insert_after_on_loan
BEFORE INSERT ON on_loan             -- !!!
FOR EACH ROW EXECUTE PROCEDURE check_onloan();

RETURN NEW对于AFTER触发器完全没有意义。 The manual:

  

在操作后触发的行级触发器的返回值将被忽略,因此它们可以返回NULL

我的有根据的猜测:您想要一个BEFORE触发器。剩下要做的就是提出一个例外。在进行工作之前检查 比以后回滚要便宜。为此,通常使用IF EXISTS ...而不是计数来检查是否存在。然后,您无需定义任何变量,也无需定义DECLARE部分。

相关:

显然,在此设计中,您需要为表in_gallery使用另一个镜像触发器-可能一开始并不理想。

无论您怎么做,都会有剩余比赛条件。在并发写入负载下,多个事务可能会尝试几乎同时在两个表中输入相同的p_id,但在 other 表中却看不到p_id,并且毕竟在两个表中输入它。它有助于缩短交易时间以最大程度地缩短时间范围,但问题仍然存在。

一个干净的解决方案是使用单个表painting和一个boolean标志来指示其状态。一次只能拥有一个状态。详细信息取决于您的完整情况...

此外:重新考虑Postgres中标识符的CaMeL大小写拼写。

本文链接:https://www.f2er.com/3004567.html

大家都在问