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?
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.
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.
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;