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;