我的 PLSQL 触发器没有循环遍历表
Posted
技术标签:
【中文标题】我的 PLSQL 触发器没有循环遍历表【英文标题】:My PLSQL trigger is not looping through the table 【发布时间】:2019-04-30 16:16:33 【问题描述】:我有一个小组项目,我们正在使用 PLSQL 来制作购物车应用程序。我们正在创建一个触发器以取消购物车并将所有商品退回库存。就像现在一样,如果您将多个商品添加到购物车,当触发器运行时,它只会添加一个产品的库存,而不是全部,因此由于某种原因,触发器不会循环。我们的项目明天到期,所以请帮忙!
create or replace TRIGGER Cancel
Before delete on sc_cart
For each row
DECLARE
ws_prod_id number(3,0);
ws_item_quantity_in_cart number(7,0);
BEGIN
/*product and quantity in cart*/
select max(item_product_id), max(item_quantity_in_cart) into ws_prod_id, ws_item_quantity_in_cart
from sc_items
where item_cart_id = :old.cart_id;
update sc_product set prod_quan_avail = prod_quan_avail + ws_item_quantity_in_cart where ws_prod_id = prod_id;
update sc_product set prod_quan_sold = prod_quan_sold - ws_item_quantity_in_cart where ws_prod_id = prod_id;
delete from sc_items
where :old.cart_id = item_cart_id;
END;
我们需要代码遍历表格的每一行并将购物车中的每件商品退回库存。
【问题讨论】:
为什么会有“循环”?触发器不循环,并且您没有编写任何循环。你得到一个 product_id 然后你就停下来了。 【参考方案1】:我敦促您不要将所有这些代码都放在触发器中,而是像这样创建一个 cancel_order 过程:
CREATE OR REPLACE PROCEDURE cancel_card (cart_id_in IN INTEGER)
IS
ws_prod_id NUMBER (3, 0);
ws_item_quantity_in_cart NUMBER (7, 0);
BEGIN
/*product and quantity in cart*/
SELECT MAX (item_product_id), MAX (item_quantity_in_cart)
INTO ws_prod_id, ws_item_quantity_in_cart
FROM sc_items i
WHERE i.item_cart_id = cancel_card.cart_id_in;
UPDATE sc_product p
SET prod_quan_avail = prod_quan_avail + ws_item_quantity_in_cart,
prod_quan_sold = prod_quan_sold - ws_item_quantity_in_cart
WHERE p.prod_id = cancel_card.ws_prod_id;
DELETE FROM sc_items o
WHERE i.cart_id = cancel_card.cart_id_in;
DELETE FROM sc_cart c
WHERE c.cart_id = cancel_card.cart_id_in;
END;
然后您可以根据需要调用此过程,但不是从触发器内部调用。
您应该避免在触发器中使用 SQL 语句。副作用和变异表错误的可能性太大。
【讨论】:
【参考方案2】:当你这样做时:
SELECT MAX (item_product_id), MAX (item_quantity_in_cart)
INTO ws_prod_id, ws_item_quantity_in_cart
FROM sc_items i
WHERE i.item_cart_id = cancel_card.cart_id_in;
您只是选择一 (1) 个产品 => max(item_product_id)
所以,这是唯一更新的产品,更糟糕的是,它最终会从另一个产品更新为 max(qty)...
您需要一个购物车产品的光标,并为每个产品进行必要的更新。
触发器没有好坏之分,但作为一个基本规则,我完全同意 Steven Feuerstein 的评论,你应该避免它们。但有时你不能。
也许更好的设计是混合设计: - 构建一个基于购物车 id 清除购物车的存储过程 - 从触发器(如果你真的必须)或从外部(购物车管理过程)调用该过程作为更好的选择。
【讨论】:
以上是关于我的 PLSQL 触发器没有循环遍历表的主要内容,如果未能解决你的问题,请参考以下文章
如果 Column_X 更新,PLSQL 触发器记录对审计表的更新
oracle(sql)基础篇系列——PLSQL游标存储过程触发器
Oracle-4 - :超级适合初学者的入门级笔记:plsql,基本语法,记录类型,循环,游标,异常处理,存储过程,存储函数,触发器