我有一个小组项目,我们正在使用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;
我们需要代码来遍历表格的每一行,并将购物车中的每件物品退还给库存。
答案 0 :(得分:2)
我敦促您不要将所有这些代码都放入触发器中,而应创建如下的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语句。副作用和突变表错误的可能性太大。
答案 1 :(得分: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)进行更新...
您需要一个光标查看购物车产品,并针对每种产品进行必要的更新。
触发器不是好事,但作为基本规则,我完全同意史蒂文·费尔斯坦的观点,应避免使用它们。但是有时候你做不到。
也许更好的设计可能是混合设计: -构建基于购物车ID清除购物车的存储过程 -从触发器(如果确实需要)或从外部(购物车管理过程)调用该过程作为更好的选择。