Вы движетесь в правильном направлении - сначала создайте свои типы
CREATE TYPE myEntry
AS
OBJECT
(attr1 NUMBER,
attr2 VARCHAR2(20)
);
CREATE TYPE myCollection AS TABLE OF myEntry;
Далее некоторые примеры функций, возвращающих «строки» вашей коллекции
CREATE OR REPLACE FUNCTION ExampleMyCollection1
RETURN myCollection
IS
lCol myCollection := myCollection(); /* Must initialise empty collection */
BEGIN
lCol.EXTEND(1000);
/* Populate the collection entries with objects */
FOR i IN 1..1000 LOOP
lCol(i) := myEntry(i,'An entry for '||i);
END LOOP;
RETURN lCol;
END ExampleMyCollection1;
SELECT * FROM TABLE(ExampleMyCollection1);
Variation - на этот раз мы используем конвейерную обработку, чтобы результаты возвращались в запрос по мере их создания. Обратите внимание, что, несмотря на то, что это функция, нет конечного ВОЗВРАТА для функции PIPELINED.
CREATE OR REPLACE FUNCTION ExampleMyCollection2
RETURN myCollection PIPELINED
IS
BEGIN
FOR i IN 1..1000 LOOP
PIPE ROW(myEntry(i,'An entry for '||i));
END LOOP;
END ExampleMyCollection2;
SELECT * FROM TABLE(ExampleMyCollection2);
Чтобы заменить вашу временную таблицу чисто данными в памяти, вам понадобится что-то для хранения вашей коллекции, то есть в пакете с состоянием.
CREATE OR REPLACE PACKAGE pMyCollection
AS
PROCEDURE AddEntry(entry IN myEntry);
FUNCTION fCurrentCollection RETURN myCollection;
PROCEDURE ClearEntries;
END pMyCollection;
CREATE OR REPLACE PACKAGE BODY pMyCollection
AS
/* Stateful variable to hold the collection */
pCollection myCollection := myCollection();
PROCEDURE AddEntry(entry IN myEntry)
IS
BEGIN
pCollection.EXTEND;
pCollection(pCollection.LAST) := entry;
END;
PROCEDURE ClearEntries
IS
BEGIN
pCollection.DELETE;
END ClearEntries;
FUNCTION fCurrentCollection
RETURN myCollection
IS
BEGIN
/* Return whole collection - we could use pipelining and parameters to return partial elements */
RETURN pCollection;
END fCurrentCollection;
END pMyCollection;