2010-05-13 2 views
16

Я пытаюсь создать функцию в пакете, которая возвращает таблицу. Я надеюсь вызвать функцию один раз в пакете, но иметь возможность повторно использовать свои временные интервалы данных. Хотя я знаю, что создаю временные таблицы в Oracle, я надеялся сохранить вещи СУХОЙ.Создайте функцию Oracle, которая возвращает таблицу

До сих пор, это то, что у меня есть:

Заголовок:

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; 

тела:

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; 

Заголовок компилирует, тело не делает. Одно сообщение об ошибке - «Недостаточно значений», что, вероятно, означает, что я должен выбирать в MEASURE_RECORD, а не в MEASURE_TABLE.

Что мне не хватает?

ответ

27

Я думаю, что вы хотите pipelined table function.

Что-то вроде этого:

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; 

Для простоты я убрал свои параметры и не реализовать цикл в функции, но вы можете увидеть принцип.

Использование:

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. 
+0

Я предполагаю, что использование курсора будет более ресурсоемким (т. Е. Медленнее), чем использование временной таблицы. Я прав? Мне нужно сгруппировать результаты этой функции. Означает ли это ваши рекомендации? – craig

+0

Что касается курсора, да, я считаю, что они не очень хороши для производительности, поэтому, скорее всего, быстрее сделать BULK COLLECT, как сказал Тони, а затем перебрать массив. Это будет зависеть от количества строк, с которыми вы имеете дело, и других соображений производительности. Что касается группировки результатов, я не уверен, но кажется вероятным, что временная таблица была бы более эффективной, чем конвейерная функция в любом случае. Я бы предложил больше исследований (или еще лучше экспериментировал). Я задал бы вопрос на http://asktom.oracle.com. –

+0

Просьба пояснить нижний план. –

3

Чтобы вернуть всю таблицу сразу можно изменить ВЫБРАТЬ к:

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

Это целесообразно только для результатов, которые не слишком велики, так как все они должны накапливаться в памяти перед возвратом; в противном случае рассмотрите конвейерную функцию, предложенную Чарльзом, или вернув КУРСОР REF.

+0

спасибо за понимание. – craig

0
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

Каков синтаксис для вызова этой функции? 'select * from TABLE (TEST.GET_UPS (...))'? – craig

Смежные вопросы