繁体   English   中英

PostgreSQL触发函数获取堆栈,并且不更新表

[英]PostgreSQL Trigger Function get stack and does not update the table

我有一个调用函数的触发器。 它基本上必须在更新后更新同一表。 但是它会得到堆栈,并且不会更新任何内容。

这是我的触发器:

    CREATE OR REPLACE FUNCTION invtransferences_products_after() 
    RETURNS TRIGGER AS 
$BODY$
DECLARE
    TR invtransferences_products%ROWTYPE;
    v_transfer_cost NUMERIC;
BEGIN
    IF(TG_OP='INSERT') THEN
        TR := NEW;
        RAISE NOTICE 'INVTRANSFERENCE PRODUCT ADDED %',TR.id;
        UPDATE invtransferences_products  
        SET product_cost = (get_product_composition_cost(product_id, 0)*quantity )
        WHERE invtransferences_products.id=TR.id;
    ELSE
        IF (TG_OP='UPDATE') THEN
            TR := NEW;
            RAISE NOTICE 'INVTRANSFERENCE PRODUCTS UPDATED %',TR.id;
            UPDATE invtransferences_products  
            SET product_cost = (get_product_composition_cost(product_id, 0)*quantity )
            WHERE invtransferences_products.id=TR.id;
        END IF;
    END IF;
    RETURN TR;
END
$BODY$
LANGUAGE plpgsql;

这是我的表invtransferences_products:

CREATE TABLE invtransferences_products
(
   id                  serial      NOT NULL,
   invtransference_id  bigint       NOT NULL,
   product_id          bigint       NOT NULL,
   quantity            numeric      DEFAULT 1 NOT NULL,
   created             timestamp    DEFAULT now() NOT NULL,
   modified            timestamp,
   rcv_quantity        numeric      DEFAULT 0 NOT NULL,
   pnd_quantity        numeric      DEFAULT 0 NOT NULL,
   product_cost        numeric
);

ALTER TABLE invtransferences_products
   ADD CONSTRAINT invtransferences_products_pkey
   PRIMARY KEY (id);

ALTER TABLE invtransferences_products
  ADD CONSTRAINT invtransferences_products_invtransference_id_fkey FOREIGN KEY (invtransference_id)
  REFERENCES invtransferences (id)
  ON UPDATE CASCADE
  ON DELETE CASCADE;

COMMIT;

怎么了?? 请帮助。

问题在于触发器函数中的UPDATE语句导致触发器再次触发。

代替发布单独的更新,您应该在NEW中处理数据。

就像是:

CREATE OR REPLACE FUNCTION invtransferences_products_after() 
    RETURNS TRIGGER AS 
$BODY$
BEGIN
    IF(TG_OP='INSERT') THEN
        RAISE NOTICE 'INVTRANSFERENCE PRODUCT ADDED %',NEW.id;
    ELSE
        IF (TG_OP='UPDATE') THEN
            RAISE NOTICE 'INVTRANSFERENCE PRODUCTS UPDATED %',NEW.id;
        END IF;
    END IF;

    NEW.product_cost := get_product_composition_cost(NEW.product_id,0)*NEW.quantity ;
    RETURN NEW;
END
$BODY$
LANGUAGE plpgsql;

小提琴在: SQLFiddle

此触发器将导致无限递归,最终导致超出堆栈深度限制错误,因为每次在同一表上发生INSERT / UPDATE时,它都会发布该表的另一个UPDATE。

解决方法是:

 UPDATE invtransferences_products  
        SET product_cost = (get_product_composition_cost(product_id, 0)*quantity )
        WHERE invtransferences_products.id=TR.id;

它应该这样做:

  NEW.product_cost := get_product_composition_cost(NEW.product_id, 0)*NEW.quantity;

并将触发器声明为更新之前或插入之前运行(而不是在运行之后)。

那是更合乎逻辑的方法。

解决方法是,也可以在触发器之外阻止递归。 在PostgreSQL中的防止递归触发器中得到了回答。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM