2010-11-30 52 views
3

J'essaie d'écrire une fonction d'agrégat personnalisée dans Oracle et de regrouper cette fonction dans un package avec d'autres fonctions que j'ai. A titre d'exemple (pour simuler le problème que j'ai) suppose que mon agrégation personnalisé pour faire une sommation des nombres ressemble:Fonction d'agrégat personnalisée à l'intérieur d'un package

CREATE OR REPLACE TYPE SUM_AGGREGATOR_TYPE AS OBJECT (
    summation NUMBER, 

    STATIC FUNCTION ODCIAggregateInitialize(agg_context IN OUT 
     SUM_AGGREGATOR_TYPE) RETURN NUMBER, 

    MEMBER FUNCTION ODCIAggregateIterate(self IN OUT SUM_AGGREGATOR_TYPE, 
     next_number IN NUMBER) RETURN NUMBER, 

    MEMBER FUNCTION ODCIAggregateMerge(self IN OUT SUM_AGGREGATOR_TYPE, 
     para_context IN SUM_AGGREGATOR_TYPE) RETURN NUMBER, 

    MEMBER FUNCTION ODCIAggregateTerminate(self IN SUM_AGGREGATOR_TYPE, 
     return_value OUT NUMBER, flags IN NUMBER) RETURN NUMBER 
); 

CREATE OR REPLACE TYPE BODY SUM_AGGREGATOR_TYPE IS 

    STATIC FUNCTION ODCIAggregateInitialize(agg_context IN OUT 
    SUM_AGGREGATOR_TYPE) 
     RETURN NUMBER IS 
    BEGIN 
    agg_context := SUM_AGGREGATOR_TYPE(NULL); 
    RETURN ODCIConst.Success; 
    END; 


    MEMBER FUNCTION ODCIAggregateIterate(self IN OUT SUM_AGGREGATOR_TYPE, 
    next_number IN NUMBER) 
     RETURN NUMBER IS 
    BEGIN 
    IF self.summation IS NULL THEN 
     self.summation := next_number; 
    ELSIF summation IS NOT NULL THEN 
     self.summation := self.summation + next_number; 
    END IF; 
    RETURN ODCIConst.Success; 
    END; 

    MEMBER FUNCTION ODCIAggregateMerge(self IN OUT SUM_AGGREGATOR_TYPE, 
    para_context IN SUM_AGGREGATOR_TYPE) 
     RETURN NUMBER IS 
    BEGIN 
    self.summation := self.summation + para_context.summation; 
    RETURN ODCIConst.Success; 
    END; 

    MEMBER FUNCTION ODCIAggregateTerminate(self IN SUM_AGGREGATOR_TYPE, 
    return_value OUT NUMBER, flags IN NUMBER) 
     RETURN NUMBER IS 
    BEGIN 
    return_value := self.summation; 
    return ODCIConst.Success; 
    END; 

END; 

Si j'écris la définition de fonction suivante:

CREATE OR REPLACE FUNCTION MY_SUM(input NUMBER) 
    RETURN NUMBER PARALLEL_ENABLE AGGREGATE USING SUM_AGGREGATOR_TYPE; 

et la déclaration de type correspondante à tester:

CREATE OR REPLACE TYPE VECTOR 
IS 
    TABLE OF NUMBER; 

cette déclaration:

select my_sum(column_value) from table(vector(1, 2, 1, 45, 22, -1)); 

donne le bon résultat de 70. Cependant, la création d'un package avec la définition de la fonction:

CREATE OR REPLACE PACKAGE MY_FUNCTIONS AS 
    FUNCTION MY_SUM(input NUMBER) 
    RETURN NUMBER PARALLEL_ENABLE AGGREGATE USING SUM_AGGREGATOR_TYPE; 
END; 

et de l'appeler via:

select MY_FUNCTIONS.my_sum(column_value) from table(vector(1, 2, 1, 45, 22, -1)); 

explose avec

ORA-00600: internal error code, arguments: [17090], [], [], [], [], [], [], [], [], [], [], [] 

Est-il possible d'avoir des fonctions agrégées personnalisées imbriquées dans les déclarations de paquet?

+1

'ORA-00600' indique généralement un bogue Oracle - parfois en raison de combinaisons inattendues de fonctionnalités. Quelle version exacte d'Oracle utilisez-vous? –

+0

J'utilise Oracle 11g Release 2 (11.2.0.1.0). – wcmatthysen

+0

Avez-vous des nouvelles à ce sujet? J'ai aussi des problèmes, cependant, dans mon cas, la connexion est interrompue 'ORA-03113: fin de fichier sur le canal de communication'. Je suppose que c'est encore pire que le 'ORA-00600'. Quand je vérifie 'SELECT * FROM ALL_PROCEDURES', je peux voir que l'agrégat défini par l'utilisateur a été correctement créé et enregistré ... –

Répondre

7

Oracle utilise ORA-00600 pour signaler des exceptions non gérées, c'est-à-dire des bogues. Le premier argument indique l'exception; ORA-17090 est une "opération non autorisée" générique. Ils sont souvent limités à des permutations spécifiques de la version de base de données et de la plate-forme OS. D'autres fois, cela signifie simplement que nous faisons quelque chose de vraiment inhabituel.

Est-ce que l'inclusion d'une fonction d'agrégat personnalisée à l'intérieur d'un paquet est considérée comme "vraiment inhabituelle"? Pas certain. Nous sommes certainement autorisés à inclure des fonctions de cartouche de données dans les fonctions PL/SQL. Mais les agrégats définis par l'utilisateur sont un cas particulier d'ODCI. Alors que la documentation n'a pas de règle explicite contre les paquets, tous les exemples implémentent l'agrégat en utilisant CREATE FUNCTION.

Alors, que faire? Eh bien, les messages ORA-00600 nécessitent l'intervention d'Oracle Support, car il nécessite un correctif. Si vous avez un compte Support, vous pouvez find out more about this particular issue here. Vous devrez augmenter un iTAR pour obtenir plus de résolution. Sinon, je crains que vous n'ayez probablement pas de chance.

+0

Etrange que ce n'est pas pris en charge. Je posterai ceci sur les forums Oracle pour voir ce qu'ils ont à dire. – wcmatthysen

+0

Création d'un post sur le forum Oracle: http://forums.oracle.com/forums/thread.jspa?threadID=2137501&tstart=0 afin que les gars d'Oracle puissent suivre cette question. – wcmatthysen

+1

Par une question j'ai demandé [ici] (http://stackoverflow.com/questions/18215415/how-to-debug-a-user-defined-aggregate-function-in-oracle-11g), il semble qu'un utilisateur La fonction d'agrégat définie fonctionne lorsque vous créez uniquement la fonction mais qu'elle ne fonctionne pas dans un package. Dans mon cas (qui est ~ 3 ans plus tard), il n'y a pas d'erreur mais il renvoie une sortie incorrecte. Donc, à quelqu'un d'autre qui, comme moi, trébuche sur cette question: si vos fonctions d'agrégat définies par l'utilisateur ne fonctionne pas dans un paquet, essayez d'utiliser simplement une fonction. – Lawtonfogle