2011-12-07 99 views
0

我一直在尝试实现这个触发器一段时间,并正在取得进展(我想!),但现在我得到一个突变错误。触发器计算小计

我在这里有三个实体(这里是相关的),Customer_Order(总等),Order_Line(数量,小计等)和产品(库存,价格)。 Order_line是一个链接实体,因此一个产品可以有很多的order_lines,而customer_order可以有很多order_lines,但是order_line只能在一个订单中出现一次,并且只能包含一个产品。触发器的目的是从order_line(或实际上我认为的产品的价格)和order_line的数量中取小计,乘以它们并更新新的order_line的小计。

因此,我用我的产品外键,数量3和价格4.00插入一个order_line,触发器将两个乘以等于12并更新小计。现在,我认为在这里使用价格而不是Order_line的小计来修正突变错误是正确的(这是因为我要求触发器更新触发语句访问的表,对吗?),但是我是否解决数量问题?数量并不总是与库存相同的价值,它必须小于或等于库存,所以有人知道我可以如何解决这个问题从产品中选择并更新order_line?谢谢。

CREATE OR REPLACE TRIGGER create_subtotal 
BEFORE INSERT OR UPDATE ON Order_Line 
for each row 
DECLARE 
currentSubTotal order_line.subtotal%type; 
currentQuantity order_line.quantity%type; 
BEGIN 
select order_line.subtotal,order_line.quantity 
into currentSubTotal,currentQuantity 
from order_line 
where product_no = :new.product_no; 
IF (currentquantity>-1) then 

update order_line set subtotal= currentSubTotal * currentQuantity where  line_no=:new.line_no; 

END IF; 
END; 
. 
run 

编辑:我想我可以使用:new语法来使用触发语句中的数量值。我会尝试这个,但我会很感激确认和帮助,谢谢。

回答

1

这听起来像你想要的东西像

CREATE OR REPLACE TRIGGER create_subtotal 
    BEFORE INSERT OR UPDATE ON order_line 
    FOR EACH ROW 
DECLARE 
    l_price products.price%type; 
BEGIN 
    SELECT price 
    INTO l_price 
    FROM products 
    WHERE product_no = :new.product_no; 

    IF(:new.quantity > -1) 
    THEN 
    :new.subtotal := :new.quantity * l_price; 
    END IF; 
END; 

如果这是比其他的东西但是,从这个触发器中的PRODUCTS表中扣除价格并没有意义。据推测,产品的价格会随着时间而改变。但订单下达时,价格是固定的。如果触发器仅在INSERT上定义,则获取当前价格可能是合理的。但是,如果您想在更新行时重新计算行的小计,那么您需要在订单发出时获取价格(并且假定您不会向同一个客户收取不同的价格时间)。

从规范化的角度来看,它也往往没有意义存储计算字段的第一位。将数量和价格存储在order_line表中,然后计算视图中该行的小计(或者,如果您使用11g作为表中的虚拟列),将会更有意义。

+0

+1。 (我没有测试代码,在数据库设计的早期阶段,我只能在家*使用Oracle *)。 –

1

突变错误不会发生,因为您正在更新表;它发生的原因是您从正在更新的表中查询。

如果我理解正确,你想做什么:

CREATE OR REPLACE TRIGGER create_subtotal 
BEFORE INSERT OR UPDATE ON Order_Line 
for each row 
DECLARE 
    currentPrice products.price%TYPE; 
BEGIN 
    -- Get the current price for the product 
    SELECT price INTO currentPrice FROM products WHERE product_no = :new.product_no; 

    -- Set the new subtotal to the current price multiplied by the order quantity 
    :new.subtotal := currentPrice * :new.quantity; 
END; 
/

(我不清楚为什么你有低于0的量的测试,并且要在这种情况下发生了什么如果。要设置在这种情况下,小计为NULL或0,它应该是很容易修改以上。)