2010-11-24 5 views
2

J'ai un problème avec Oracle 10g et l'utilisation de la fonction COLLECT. J'ai seulement découvert son existence ce matin mais j'ai un problème qui pourrait être résolu en l'utilisant en association avec la condition member of.Fonction Oracle COLLECT et types

Initialement, j'ai écrit le code ci-dessous, qui est revenu avec l'erreur "ORA_00932: types de données incohérents: attendu UDT obtenu -".

with my_tab as (
    select 1 as cola, 1 as colb from dual union all 
    select 1 as cola, 2 as colb from dual union all 
    select 2 as cola, 3 as colb from dual union all 
    select 2 as cola, 4 as colb from dual union all 
    select 3 as cola, 3 as colb from dual union all 
    select 3 as cola, 4 as colb from dual union all 
    select 4 as cola, 1 as colb from dual union all 
    select 4 as cola, 2 as colb from dual 
) 
select 
    cola, 
    colb_vals 
from (
    select 
    cola, 
    collect(colb) as colb_vals 
    from my_tab 
    group by cola 
) 
where 2 member of colb_vals 

Je trouve cela un peu étrange puisque dans Oracle 10.2.4.0, il semble que la base de données créera un système temporaire généré le type défini par l'utilisateur, et l'utiliser. Si je supprime la condition, (where 2 member of colb_vals) alors le code s'exécutera et montrera les données récupérées incluses l'UDT temporaire (nommé SYSTPblahblahblah ==). Après un peu plus de recherche, j'ai réalisé que je pouvais résoudre ce problème en utilisant CREATE TYPE puis en utilisant la fonction CAST pour changer le type de la table imbriquée. Qui a fonctionné.

Ce employais CREATE TYPE number_ntt as TABLE OF NUMBER; et le remplacement collect(colb) avec cast(collect(colb) as number_ntt)

J'ai ensuite essayé d'utiliser un type de tableau imbriqué créé dans un paquet, puisque je ne ai besoin de ce type à être disponible pour une requête particulière dans une procédure en une seule paquet. Et je ne pouvais pas le faire fonctionner.

create or replace package mike_temp_pkg as 
    type number_ntt is table of number; 
end mike_temp_pkg; 

Et cette fois remplaçant collect(colb) avec cast(collect(colb) as mike_temp_pkg.number_ntt)

Il en est résulté ORA-00932: type de données non valide.

La question que j'ai est en deux parties: vraiment

  1. Pourquoi le système généré par l'utilisateur travail de type défini pour le select mais pas pour le member of? Pourquoi le type doit-il être un type SQL et non un type PL/SQL dans un package ? Je ne définis pas vraiment les types souvent, donc il peut y avoir une réponse simple à cette question .

Répondre

2

(1)

Les états de documentation de la fonction COLLECT "Pour obtenir les résultats de cette fonction, vous devez l'utiliser dans une fonction CAST." Je suppose qu'il n'est tout simplement pas conçu pour prendre en charge des utilisations, sauf une simple vidage de son contenu, sauf si vous l'avez casté dans un type défini.

(2)

L'analyseur SQL n'a pas connaissance de ou l'accès à des types définis dans les blocs PL/SQL. Même lorsque vous exécutez une instruction SQL à l'intérieur du code PL/SQL, l'instruction est essentiellement transmise à un analyseur indépendant (avec les noms de variable PL/SQL remplacés par des espaces réservés aux variables de liaison).

+0

Je pense qu'une partie de la raison pour laquelle je pensais que la partie 2 pourrait être possible est parce que j'ai utilisé des types PL/SQL dans le passé, mais avec des fonctions PIPELINED où, je suppose, le mot clé TABLE peu de pont entre les mondes SQL et PL/SQL dans ce cas. –

+0

Dans une fonction pipelined, les types SQL sont créés implicitement. http://blog.sydoracle.com/2007/03/pipelined-functions-implicitly-create.html –

+0

@Gary Merci pour le lien. Je suis de plus en plus confus par le jour avec l'interaction entre SQL et PL/SQL! –

Questions connexes