Triggers
[30 min]
Un ensemble de règles de gestion est défini afin de gérer le stock des produits du projet MediaTek. La politique suivante a été admise :
après chaque vente, la quantité vendue est soustraite de la quantité disponible indiquée dans une colonne de la table des produits,
si cette quantité (disponible) est inférieure à un "seuil" alors insérer un avertissement dans une table de journalisation avec la date du jour, le numéro de produit, et stock restant après mise à jour.
Question
Créer un déclencheur permettant de mettre à jour la quantité disponible dans la table produit à chaque insertion dans la table ligne facture (traitement du point 1).
Indice
CREATE TRIGGER TR_STOCK_AUDIT
BEFORE INSERT ON ligne_fact
Indice
Il s'agit d'un trigger qui cherche à faire une modification pour chaque insertion : utilisez un trigger "for each row".
FOR EACH ROW
Indice
Utilisez une requête update pour effectuer la mise à jour avec une condition sur le numéro de produit.
UPDATE ...
SET ...
WHERE num=:new.produit;
Solution
CREATE TRIGGER TR_STOCK_AUDIT
BEFORE INSERT ON ligne_fact
FOR EACH ROW
BEGIN
UPDATE PRODUIT p
SET p.stock=p.stock - :new.qte
WHERE p.num= :new.produit;
END;
/
Question
Testez votre trigger TR_STOCK_AUDIT en supprimant et en réinsérant les données des tables FACTURE et LIGNE_FACT.
Solution
delete from LIGNE_FACT;
delete from FACTURE;
-- INSERT INTO FACTURE, LIGNE_FACT
-- Facture 1
insert into FACTURE(num, client, date_etabli) values(
1,
2,
to_date('20122000','DDMMYYYY')
);
insert into LIGNE_FACT(facture, produit, qte) values(
1,
1,
1
);
insert into LIGNE_FACT(facture, produit, qte) values(
1,
2,
2
);
-- Facture 2
insert into FACTURE(num, client, date_etabli) values(
2,
2,
to_date('01012001','DDMMYYYY')
);
insert into LIGNE_FACT(facture, produit, qte) values(
2,
1,
2
);
insert into LIGNE_FACT(facture, produit, qte) values(
2,
3,
1
);
insert into LIGNE_FACT(facture, produit, qte) values(
2,
2,
2
);
-- Facture 3
insert into FACTURE(num, client, date_etabli) values(
3,
2,
to_date('17112004','DDMMYYYY')
);
insert into LIGNE_FACT(facture, produit, qte) values(
3,
1,
2
);
insert into LIGNE_FACT(facture, produit, qte) values(
3,
2,
4
);
insert into LIGNE_FACT(facture, produit, qte) values(
3,
3,
1
);
-- Facture 4
insert into FACTURE(num, client, date_etabli) values(
4,
3,
to_date('14012004','DDMMYYYY')
);
insert into LIGNE_FACT(facture, produit, qte) values(
4,
2,
1
);
insert into LIGNE_FACT(facture, produit, qte) values(
4,
3,
1
);
-- Facture 5
insert into FACTURE(num, client, date_etabli) values(
5,
4,
to_date('19022004','DDMMYYYY')
);
insert into LIGNE_FACT(facture, produit, qte) values(
5,
1,
2
);
insert into LIGNE_FACT(facture, produit, qte) values(
5,
3,
3
);
insert into LIGNE_FACT(facture, produit, qte) values(
5,
2,
4
);
-- Facture 6
insert into FACTURE(num, client, date_etabli) values(
6,
4,
to_date('17032004','DDMMYYYY')
);
insert into LIGNE_FACT(facture, produit, qte) values(
6,
1,
7
);
insert into LIGNE_FACT(facture, produit, qte) values(
6,
2,
3
);
insert into LIGNE_FACT(facture, produit, qte) values(
6,
3,
1
);
commit;
select * from PRODUIT;
Question
Créer la table de journalisation.
Solution
CREATE TABLE audit_stock (
datealert DATE,
produit NUMBER,
stock NUMBER,
CONSTRAINT FK_AUDIT_STOCK_PRODUIT FOREIGN KEY (produit) REFERENCES PRODUIT(num)
);
Question
Modifiez votre déclencheur de telle façon qu'après la mise à jour, il teste si le stock est inférieur à une valeur seuil de 5. Si le stock est inférieur à ce seuil, alors il devra insérer les informations adéquates dans la table de journalisation (traitement du point 2).
Solution
CREATE OR REPLACE TRIGGER TR_STOCK_AUDIT
BEFORE INSERT ON ligne_fact
FOR EACH ROW
DECLARE
new_stock NUMBER;
new_id NUMBER;
BEGIN
UPDATE PRODUIT p
SET p.stock = p.stock - :new.qte
WHERE p.num = :new.produit;
SELECT stock INTO new_stock
FROM produit
WHERE num = :new.produit;
IF new_stock <= 5 THEN
INSERT INTO AUDIT_STOCK (datealert, produit, stock)
VALUES (
sysdate,
:new.produit,
new_stock
);
END IF;
END;
/
SHOW ERRORS
Question
Testez à nouveau votre trigger jusqu'à obtenir au moins un message.
Solution
insert into FACTURE(num, client, date_etabli) values(
7,
2,
to_date('20122000','DDMMYYYY')
);
insert into LIGNE_FACT(facture, produit, qte) values(
7,
1,
90
);
select * from audit_stock;