2010-05-06 9 views
9

est ici un paquet avec deux fonctions canalisées:fonction Pipelined appeler une autre fonction pipelinée

create or replace type tq84_line as table of varchar2(25); 
/

create or replace package tq84_pipelined as 

    function more_rows return tq84_line pipelined; 
    function go  return tq84_line pipelined; 

end tq84_pipelined; 
/

Ant le corps de package correspondant:

create or replace package body tq84_pipelined as 

    function more_rows return tq84_line pipelined is 
    begin 

     pipe row('ist'); 
     pipe row('Eugen,'); 

     return; 

    end more_rows; 

    function go return tq84_line pipelined is 
    begin 

     pipe row('Mein'); 
     pipe row('Name'); 

     /* start */ 
     for next in (
      select column_value line from table(more_rows) 
     ) 
     loop 
      pipe row(next.line); 
     end loop; 
     /* end */ 

     pipe row('ich'); 
     pipe row('weiss'); 
     pipe row('von'); 
     pipe row('nichts.'); 

    end go; 

end tq84_pipelined; 
/

L'important est que aller sorte de appels more_rows avec le for next in ... entre /* start */ et /* end */

Je peux utiliser le package comme suit:

select * from table(tq84_pipelined.go); 

Tout cela est bien beau, mais j'espère que je pourrais remplacer les lignes entre /* start */ et /* end */ avec un simple appel de more_rows.

Cependant, ce n'est évidemment pas possible, car il génère un PLS-00221: 'MORE_ROWS' n'est pas une procédure ou est indéfini.

Donc, ma question: est-ce qu'il n'y a vraiment aucun moyen de raccourcir la boucle?

EDIT

De toute évidence, des réponses à ce jour, ma question n'a pas été claire.

L'emballage, comme indiqué, fonctionne.

Mais je suis embêté avec les 6 (c'est-à-dire: SIX) lignes entre les marqueurs /* start */ et /* end */. Je voudrais les remplacer par une seule ligne. Mais je n'ai trouvé aucun moyen de le faire.

Répondre

7

Le point de fonctions pipelined est de fournir des fonctions TABLE(). Je ne pense pas qu'il y ait moyen de l'éviter. Malheureusement, nous devons assigner sa sortie à une variable PL/SQL. On ne peut pas attribuer une fonction à une table pipelinée imbriquée comme celui-ci nt := more_rows; en raison de

PLS-00653: aggregate/table functions are not allowed in PL/SQL scope 

Alors SELECT ... FROM TABLE() il doit être.

J'ai une solution légèrement différente pour votre considération. Je ne sais pas si cela résout votre problème sous-jacent.

create or replace package body tq84_pipelined as 

    function more_rows return tq84_line pipelined is 
    begin 

     pipe row('ist'); 
     pipe row('Eugen,'); 

     return; 

    end more_rows; 

    function go return tq84_line pipelined is 
     nt1 tq84_line; 
     nt2 tq84_line; 
     nt3 tq84_line; 
     nt0 tq84_line; 
    begin 

     nt1 := tq84_line('Mein','Name'); 

     select * 
     bulk collect into nt2 
     from table(more_rows); 

     nt3 := tq84_line('ich','weiss','von','nichts.'); 

     nt0 := nt1 multiset union nt2 multiset union nt3; 

     for i in nt0.first..nt0.last 
     loop 
      pipe row(nt0(i)); 
     end loop; 

     return; 

    end go; 

end tq84_pipelined; 
/

Comme je suis sûr que vous êtes au courant (mais au profit d'autres demandeurs) la syntaxe MULTISET UNION pour glomming collections ensemble a été introduit dans Oracle 10g.

Cette version de GO() produit le même résultat que l'implémentation d'origine:

SQL> select * from table(tq84_pipelined.go) 
    2/

COLUMN_VALUE 
------------------------- 
Mein 
Name 
ist 
Eugen, 
ich 
weiss 
von 
nichts. 

8 rows selected. 

SQL> 
+0

Merci pour votre réponse. Mais cela n'aide pas mon 'problème' car avec cette construction je n'ai pas seulement le 'pour ... boucle ...la construction de la boucle d'extrémité, mais aussi une collecte de masse supplémentaire. Je veux dire, ce n'est pas un problème, car je peux vivre avec, mais je pensais que ce serait visuellement plus attrayant avec un simple appel d'une ligne à plus de lignes sans plus de boucles et quoi d'autre. –

0

Essayez select column_value line from table(tq84_line.more_rows) , c'est-à-dire d'inclure le nom du paquet dans la requête.

+0

'sélectionner la ligne column_value de table (more_rows)' fonctionne très bien. Le remplacement souhaité ne fonctionne pas. –

Questions connexes