如何重写触发器以避免错误“ BB_BASKET正在变异,触发器/函数可能看不到它”
作业说明:创建一个名为BB_SALESUM_TRG的触发器,当确认订单或将BB_BASKET表中的ORDERPLACED列更新为1时,该触发器将相应地更新BB_SALES_SUM。
一直在寻找解决方案,同时不更改我的作业分配,这表明查询必须是AFTER触发器,因为在确认订单后必须更新库存。其他SO建议是将AFTER更改为BEFORE或INSERT,但是BEFORE触发器会在确认之前错误地更新清单,并且INSERT不能与行级触发器一起使用。完全避免触发的其他建议对于现实世界来说是好的,但对于专门针对触发的功课却不是。
语句级触发器可以避免此问题,但是我不能将WHEN子句与语句级触发器一起使用,我认为我需要WHEN或我的代码将不考虑数量来更新表。
添加一个实用的自主事务似乎并没有消除错误
家庭作业簿中的其他类似代码也可以将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
答案 0 :(得分:2)
您需要考虑问题的逻辑。 bb_sales_sum.total_qty
是总数:即,它是所有已售商品的总和。您的触发器不会计算总数,因此(如果执行了)结果将是错误的:bb_sales_sum.total_qty
将被设置为最后一个购物篮中商品的价值,而不是所售商品的总和。
仔细阅读问题,我们会发现它在正确的方向上有所帮助:
在确认订单或将BB_BASKET表中的ORDERPLACED列更新为1时,相应地更新BB_SALES_SUM。
触发器应该仅更新和,而不是覆盖它。让我们尝试一下。
注意:这看起来不对-product_id = :new.idbasket
-但是您尚未发布完整的表格或示例数据集。另外,您还没有指定“确认订单” 的方式。因此,我将假设您的过滤逻辑是正确的。您可能需要对其进行调整。
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;
/