table正在变异,trigger/function可能看不到;需要after/row级查询

table is mutating, trigger/function may not see it; needs after/row level query

如何重写触发器以避免错误 "BB_BASKET is mutating, trigger/function may not see it"

作业说明:创建一个名为BB_SALESUM_TRG的触发器,当订单被确认或BB_BASKET table中的ORDERPLACED列更新为时,相应地更新BB_SALES_SUM 1.

一直在寻找此问题的解决方案,同时未更改我的作业分配,这表明查询必须是 AFTER 触发器,因为必须在确认订单后更新库存。其他 SO 建议是将 AFTER 更改为 BEFORE 或 INSERT,但 BEFORE 触发器会在确认之前错误地更新库存,并且 INSERT 不能与行级触发器一起使用。其他完全避免触发器的建议适用于现实世界,但不适用于专门针对触发器的作业。

语句级触发器可以避免这个问题,但我不能将我的 WHEN 子句与语句级触发器一起使用,我想我需要 WHEN 否则我的代码将更新 table 而不管数量。

添加pragma自治事务好像没有去掉错误

我的作业本中的其他类似代码将 AFTER 与游标中的 SELECT 语句一起使用没有问题,所以我不认为这是游标中的 SELECT 语句让我感到悲伤。

CREATE TABLE BB_SALES_SUM (
product_id VARCHAR2(30) PRIMARY KEY,
total_sales NUMBER(8,2),
total_qty NUMBER(10),
OrderPlaced number(1)
);

Set ServerOutput On;
CREATE OR REPLACE TRIGGER bb_salessum_trg
AFTER UPDATE OF orderplaced ON bb_basket
FOR EACH ROW
WHEN(OLD.orderplaced <> 1 AND NEW.orderplaced = 1)
DECLARE
CURSOR basketitem_cur IS
   SELECT idbasket, total, quantity, orderplaced
   FROM bb_basket
   WHERE idbasket=:NEW.idbasket;
BEGIN
   FOR basketitem_rec in basketitem_cur LOOP
    UPDATE bb_sales_sum
    SET total_qty = basketitem_rec.quantity
    WHERE product_id = basketitem_rec.idbasket;
END LOOP;
END;
/

UPDATE bb_basket SET orderplaced = 1 WHERE idbasket = 14

你需要思考问题的逻辑。 bb_sales_sum.total_qty是合计:即所有售出商品的总和。您的触发器不计算总数,因此(如果执行)结果将是错误的:bb_sales_sum.total_qty 将设置为最后一个购物篮中商品的价值,而不是售出商品的总和。

仔细阅读问题,我们会发现它在正确的方向上提供了一个推动力:

updates the BB_SALES_SUM accordingly when an order is confirmed or the ORDERPLACED column in the BB_BASKET table is updated to 1.

触发器应该只更新总和,而不是覆盖它。让我们试试这个。

注意:这看起来不对 - product_id = :new.idbasket - 但您尚未发布完整的表格集或示例数据。此外,您还没有指定如何 "an order is confirmed"。所以我假设你的过滤逻辑是正确的。您可能需要对其进行调整。

CREATE OR REPLACE TRIGGER bb_salessum_trg
AFTER UPDATE OF orderplaced ON bb_basket
FOR EACH ROW
WHEN(OLD.orderplaced <> 1 AND NEW.orderplaced = 1)
BEGIN

    UPDATE bb_sales_sum
    SET total_qty = total_qty + :new.quantity
    WHERE product_id = :new.idbasket;

END;
/