web-dev-qa-db-fra.com

Créer une fonction Oracle qui retourne une table

J'essaie de créer une fonction dans un package qui renvoie une table. J'espère appeler la fonction une fois dans le package, mais être capable de réutiliser ses données plusieurs fois. Bien que je sache que je crée des tables temporaires dans Oracle, j'espérais garder les choses au sec.

Jusqu'à présent, voici ce que j'ai:

Entête:

CREATE OR REPLACE PACKAGE TEST AS 

    TYPE MEASURE_RECORD IS RECORD (
      L4_ID VARCHAR2(50),
      L6_ID VARCHAR2(50),
      L8_ID VARCHAR2(50),
      YEAR NUMBER,
      PERIOD NUMBER,
      VALUE NUMBER
    );

    TYPE MEASURE_TABLE IS TABLE OF MEASURE_RECORD;

    FUNCTION GET_UPS(
      TIMESPAN_IN IN VARCHAR2 DEFAULT 'MONTLHY',
      STARTING_DATE_IN DATE,
      ENDING_DATE_IN DATE  
    ) RETURN MEASURE_TABLE;

END TEST;

Corps:

CREATE OR REPLACE PACKAGE BODY TEST AS 

  FUNCTION GET_UPS (
    TIMESPAN_IN IN VARCHAR2 DEFAULT 'MONTLHY',
    STARTING_DATE_IN DATE,
    ENDING_DATE_IN DATE
  ) RETURN MEASURE_TABLE IS

    T MEASURE_TABLE;

  BEGIN

        SELECT  ...
        INTO    T
        FROM    ...

      ;

  RETURN T;

  END GET_UPS;

END TEST;

L'en-tête compile, pas le corps. Un message d'erreur est «pas assez de valeurs», ce qui signifie probablement que je devrais être sélectionné dans MEASURE_RECORD plutôt que dans MEASURE_TABLE.

Qu'est-ce que je rate?

17
craig

Je pense que vous voulez une fonction de table en pipeline

Quelque chose comme ça:

CREATE OR REPLACE PACKAGE test AS

    TYPE measure_record IS RECORD(
       l4_id VARCHAR2(50), 
       l6_id VARCHAR2(50), 
       l8_id VARCHAR2(50), 
       year NUMBER, 
       period NUMBER,
       VALUE NUMBER);

    TYPE measure_table IS TABLE OF measure_record;

    FUNCTION get_ups(foo NUMBER)
        RETURN measure_table
        PIPELINED;
END;

CREATE OR REPLACE PACKAGE BODY test AS

    FUNCTION get_ups(foo number)
        RETURN measure_table
        PIPELINED IS

        rec            measure_record;

    BEGIN
        SELECT 'foo', 'bar', 'baz', 2010, 5, 13
          INTO rec
          FROM DUAL;

        -- you would usually have a cursor and a loop here   
        PIPE ROW (rec);

        RETURN;
    END get_ups;
END;

Pour plus de simplicité, j'ai supprimé vos paramètres et je n'ai pas implémenté de boucle dans la fonction, mais vous pouvez voir le principe.

Usage:

SELECT *
  FROM table(test.get_ups(0));



L4_ID L6_ID L8_ID       YEAR     PERIOD      VALUE
----- ----- ----- ---------- ---------- ----------
foo   bar   baz         2010          5         13
1 row selected.
30
Igby Largeman

Pour retourner la table entière en une fois, vous pouvez changer le SELECT en:

SELECT  ...
BULK COLLECT INTO T
FROM    ...

Ceci n'est recommandé que pour les résultats qui ne sont pas excessivement gros, car ils doivent tous être accumulés en mémoire avant d'être renvoyés; sinon, considérez la fonction pipelined telle que suggérée par Charles ou renvoyez un REF CURSOR.

3
Tony Andrews
  CREATE OR REPLACE PACKAGE BODY TEST AS 

   FUNCTION GET_UPS(
   TIMESPAN_IN IN VARCHAR2 DEFAULT 'MONTLHY',
   STARTING_DATE_IN DATE,
   ENDING_DATE_IN DATE
   )RETURN MEASURE_TABLE IS

    T MEASURE_TABLE;

 BEGIN

    **SELECT   MEASURE_RECORD(L4_ID , L6_ID ,L8_ID ,YEAR ,
             PERIOD,VALUE )  BULK COLLECT  INTO    T
    FROM    ...**

  ;

   RETURN T;

   END GET_UPS;

END TEST;
0
Yathish Manjunath