Bases de données avancées

Transcription

Bases de données avancées
Université Cergy-Pontoise
Master Informatique M1
Bases de données avancées
Exemple de requêtes continues en utilisant des déclencheurs (triggers)
On considère qu’un flux de données est représenté par une relation (table), dans laquelle les
nouveaux éléments du flux sont rajoutés par insertion.
Soit un flux de cotations boursières journalières stocké dans la table Cotation, définie par :
create table Cotation (cnom varchar2(20), cdate date, cval number);
Chaque cotation est représentée par le nom de la société cotée (cnom), la date de la cotation
(cdate) et la valeur de la cotation en euros (cval).
On considère deux requêtes continues, qui produisent respectivement les flux de sortie
suivants (on considère les tables des flux de sortie déjà créées) :
a. Cotation10EDF, qui contient la date et la valeur des cotations de la société EDF qui
dépassent une valeur de 10 euros l’action.
b. CotationMoyenne, qui contient le nom, la date et la valeur moyenne des 5 dernières
cotations de chaque société (ou de celles existantes si moins de 5 cotations
enregistrées).
On explore ici l’implémentation des requêtes continues par des triggers sur la table (flux)
Cotation, produisant les flux de sortie correspondants.
a) Requête continue produisant Cotation10EDF
On crée un trigger après insertion, par ligne, sur Cotation. La ligne insérée est testée et, si
elle répond aux critères de la requête, la date et la valeur de la cotation sont insérées dans
le flux de sortie.
create or replace trigger fluxSimple
after insert on Cotation
for each row
begin
if :NEW.cnom = 'EDF' and :NEW.cval > 10 then
insert into Cotation10EDF values(:NEW.cdate, :NEW.cval);
end if;
end;
b) Requête continue produisant CotationMoyenne
La solution naturelle, dans le même esprit que pour la requête précédente, serait la
suivante. Elle utilise un curseur qui parcourt en ordre inverse de la date les cotations de la
société pour laquelle on vient de recevoir la nouvelle cotation. Ce curseur permet de
calculer la valeur moyenne des dernières cotations.
create or replace trigger fluxFenetre
after insert on Cotation
for each row
declare
cursor fenetre is
select * from Cotation
where cnom = :NEW.cnom
order by cdate desc;
somme NUMBER := 0;
nb NUMBER := 0;
begin
for c in fenetre loop
somme := somme + c.cval;
nb := nb + 1;
exit when nb = 5;
end loop;
insert into CotationMoyenne
values(:NEW.cnom, :NEW.cdate, somme/nb);
end;
Cependant, cette solution naturelle ne fonctionne pas dans Oracle, puisque le trigger par
ligne sur insertion s’exécute pendant que la table Cotation est modifiée. En effet, lors du
déclenchement du trigger pour l’insertion d’une ligne on est en plein milieu d’une
opération INSERT qui peut en insérer plusieurs. Oracle ne permet pas dans ce cas la
consultation de la table, donc le parcours de la fenêtre avec le curseur est rejeté.
Pour éviter ce problème, on peut utiliser un espace intermédiaire pour l’arrivée des
nouvelles cotations dans le flux : une table CotationNew, qui reçoit les nouvelles cotations
juste le temps de les insérer dans Cotation. La requête continue sera implémentée comme
un trigger sur CotationNew, dans ce cas la consultation de Cotation dans le trigger sera
possible.
create or replace trigger fluxFenetre
after insert on CotationNew
for each row
declare
cursor fenetre is
select * from Cotation
where cnom = :NEW.cnom
order by cdate desc;
somme NUMBER := 0;
nb NUMBER := 0;
begin
insert into Cotation values(:NEW.cnom, :NEW.cdate, :NEW.cval);
for c in fenetre loop
somme := somme + c.cval;
nb := nb + 1;
exit when nb = 5;
end loop;
insert into CotationMoyenne
values(:NEW.cnom, :NEW.cdate, somme/nb);
end;
La table CotationNew peut être vidée automatiquement à l’aide d’un trigger par
instruction sur la commande INSERT. Un trigger sur instruction s’exécute dans Oracle
après les triggers par ligne de la même table, donc le nettoyage de la table CotationNew se
fait après avoir traité chaque ligne insérée.
create or replace trigger fluxNettoyage
after insert on CotationNew
begin
delete from CotationNew;
end;

Documents pareils