2011-12-07 3 views
0

J'ai essayé d'implémenter ce déclencheur pendant un moment maintenant et je progresse (je pense!) Mais maintenant je reçois une erreur de mutation.Déclencheur pour calculer le sous-total

Ce que j'ai ici est trois entités (qui sont pertinentes ici), Customer_Order (total etc), Order_Line (quantité, sous-total etc) et produits (stock, prix). Order_line est une entité de lien et un produit peut donc se trouver dans plusieurs lignes de commande et un client_order peut avoir plusieurs lignes de commande, mais une ligne de commande ne peut apparaître qu'une seule fois dans une commande et ne peut contenir qu'un seul produit. Le but du déclencheur est de prendre le sous-total de order_line (ou le prix des produits que je pense réellement) et la quantité de order_line, les multiplier et mettre à jour le sous-total du nouveau order_line. Donc j'insère une ligne order_line avec mon produit étranger, quantité de 3 et prix de 4.00, le déclencheur multiplie les deux par 12 et met à jour le sous-total. Maintenant, je pense qu'il est bon d'utiliser ici le prix au lieu du sous-total de Order_line pour corriger l'erreur de mutation (qui se produit parce que je demande au déclencheur de mettre à jour la table qui est accessible par l'instruction, mais comment? puis-je résoudre le problème de quantité? La quantité ne sera pas toujours la même valeur que le stock, elle doit être inférieure ou égale au stock, alors quelqu'un sait-il comment je peux résoudre ce problème pour sélectionner le produit et mettre à jour order_line? Merci.

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 

EDIT: Je pense que je pourrais utiliser la nouvelle syntaxe pour utiliser la valeur de quantité de l'instruction de déclenchement. Je vais essayer mais j'apprécierais la confirmation et l'aide encore, merci.

Répondre

1

on dirait que vous voulez quelque chose comme

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; 

Si cela est autre chose que Devoir, cependant, il n'a pas vraiment de sens de tirer le prix de la table PRODUCTS dans ce déclencheur. Vraisemblablement, le prix d'un produit va changer au fil du temps. Mais le prix est fixé pour une commande particulière lors de la commande. Si le déclencheur n'était défini que sur INSERT, il serait probablement raisonnable d'aller chercher le prix actuel. Mais si vous voulez recalculer le sous-total de la ligne lorsqu'une ligne est mise à jour, vous devez aller chercher le prix au moment de la commande (et cela suppose que vous ne facturiez pas des prix différents à des clients différents en même temps temps). Du point de vue de la normalisation, il n'est généralement pas judicieux de stocker des champs calculés en premier lieu. Il serait plus logique de stocker la quantité et le prix dans la table order_line puis de calculer le sous-total de la ligne dans une vue (ou, si vous utilisez 11g, comme une colonne virtuelle dans la table).

+0

+1 pour le texte. (Je n'ai pas testé le code.Au début de la conception de la base de données, j'ai seulement accès à Oracle * à la maison *.) –

1

L'erreur de mutation ne se produit pas parce que vous mettez à jour la table; Cela se produit car vous interrogez à partir de la table en cours de mise à jour.

Si je comprends bien ce que vous voulez faire:

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; 
/

(je ne suis pas clair pourquoi vous avez un test pour une quantité inférieure à 0, et ce que vous voulez produire dans ce cas, si. vous souhaitez définir le sous-total à NULL ou 0 dans ce cas, il devrait être assez facile de modifier ci-dessus.)

Questions connexes