Partager l'article ! Create your own aggregate function: Vous voulez agréger vos données de manière stupide et irrationnelle ? Pour vous, l'ODCIAggregate ...
Vous voulez agréger vos données de manière stupide et irrationnelle ?
Pour vous, l'ODCIAggregate ! (Et pour moi, un pense-bête de la syntaxe barbare du truc...)
1) La démarche
L'agrégation personnalisée sous Oracle s'appuie sur la création d'un objet regroupant les variables et les routines d'agrégations
On peut alors créer une fonction utilisant cette structure pour calculer le résultat voulu dans un GROUP BY.
Ensuite, lors de l'exécution :
- On appelle la fonction d'agrégation dans la requête
- Pour chaque groupe, la fonction définie :
- Instancie un objet (et donc un contexte) d'aggrégation pour chaque process de lecture parallèle
- Sur chacune de ces instances parallèles, la fonction d'itération est appelée sur chaque ligne
- Les différentes instances parallèles sont mergées itérativement (deux à deux) par appel de la fonction de fusion
- La fonction terminate renvoie le résultat définit pour le groupe traité
2) La syntaxe !
a. Spécification
CREATE TYPE MonObjAgg AS OBJECT
(
-- Définition des variables de contexte qui permettront de calculer des trucs itérativement
MaVariable1 NUMBER,
MaVariable2 NUMBER,
-- La fonction statique d'initialisation: elle retourne une instance (sous forme de paramètre out)
STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT MonObjAgg)
RETURN NUMBER,
-- La fonction d'itération : c'est le calcul à définir
-- L'instance en paramètre in out est mise à jour. Le deuxième paramètre est la valeur donnée à la fonction d'aggrégation
MEMBER FUNCTION ODCIAggregateIterate(self IN OUT MonObjAgg,
value IN NUMBER) RETURN NUMBER,
-- La fonction qui fusionne deux instances parallèles fournies en argument (à vrai dire, elle fusionne la deuxième dans la première)
MEMBER FUNCTION ODCIAggregateMerge(self IN OUT MonObjAgg,
ctx2 IN MonObjAgg) RETURN NUMBER,
-- La fonction qui renvoie le résultat final pour le GROUP BY
-- Premier paramètre : l'instance résultant du process d'aggrégation / merge
-- Second paramètre : La valeur qui sera retournée par la fonction d'agrégation dans la requête GROUP BY
-- Troisième paramètre : Euh un truc compliqué auquel je m'intéresserais peut être un autre jour
MEMBER FUNCTION ODCIAggregateTerminate(self IN MonObjAgg,
returnValue OUT NUMBER,flags IN NUMBER) RETURN NUMBER
);
/
b. Implémentation
Ben ouais, comme pour les packages, faut définir le corps maintenant...
CREATE OR REPLACE TYPE BODY MonObjAgg is
STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT MonObjAgg)
RETURN NUMBER is
begin
sctx := MonObjAgg(1, 1); -- Créer une instance de l'objet, en initialisant ses variable
RETURN ODCIConst.Success;
end;
MEMBER FUNCTION ODCIAggregateIterate(self IN OUT MonObjAgg, value IN NUMBER) RETURN NUMBER is
begin
--Ici, on définit vraiment l'itération... en stockant les résultats itératifs dans les variables (propriétés) de l'objet
--Par exemple :
self.MaVariable1 := value * self.MaVariable1;
--...
RETURN ODCIConst.Success;
end;
MEMBER FUNCTION ODCIAggregateMerge(self IN OUT MonObjAgg, ctx2 IN MonObjAgg) RETURN NUMBER is
begin
-- Merger ctx2 dans self... par exemple juste sommer les variables :
self.MaVariable1 := self.MaVariable1 + ctx2.MaVariable1;
self.MaVariable2 := self.MaVariable1 + ctx2.MaVariable2;
RETURN ODCIConst.Success;
end;
MEMBER FUNCTION ODCIAggregateTerminate(self IN MonObjAgg,
returnValue OUT NUMBER,flags IN NUMBER) RETURN NUMBER is
begin
-- Ben faut retourner le résultat. On peut faire une dernière manip genre tests, opérations en tous genre...
returnValue := self.MaVariable1 + MaVariable2; -- Mon exemple est complètement idiot, certes
RETURN ODCIConst.Success;
end;
end;
/
c. Créer le type !
CREATE OR REPLACE FUNCTION MonAgg (input NUMBER) RETURN NUMBER
PARALLEL_ENABLE AGGREGATE USING MonObjAgg;
Et si vous ne voulez pas que ça puisse paralléliser... omettez la clause PARALLEL_ENABLE ! (Sûrement évident pour vous, mais c'est un pense-bête pour
moi qui suis pas toujours très lucide :D)
Voilà voilà...
| Mai 2012 | ||||||||||
| L | M | M | J | V | S | D | ||||
| 1 | 2 | 3 | 4 | 5 | 6 | |||||
| 7 | 8 | 9 | 10 | 11 | 12 | 13 | ||||
| 14 | 15 | 16 | 17 | 18 | 19 | 20 | ||||
| 21 | 22 | 23 | 24 | 25 | 26 | 27 | ||||
| 28 | 29 | 30 | 31 | |||||||
|
||||||||||