2010-05-13 18 views
16

Bir tablo döndüren pakette bir işlev oluşturmaya çalışıyorum. Bu fonksiyonu paketin içinde bir kez çağırmayı umuyorum, ancak veri mulitple zamanlarını yeniden kullanabiliyorum. Oracle’da temp tabloları oluşturduğumu bildiğim halde, işleri DRY’de tutmayı umuyordum.Bir tablo döndüren bir Oracle işlevi oluşturun

Başlığını:

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; 

Gövde: başlık derler

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; 

, vücut değil

Şimdiye kadar, bu ben ne var. Bir hata mesajı 'yeterli değerler değil', bu muhtemelen MEASURE_TABLE yerine MEASURE_RECORD içine seçmem gerektiği anlamına geliyor.

Neyi eksik?

cevap

27

Sanırım bir pipelined table function. Böyle

şey:

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; 

Kolaylık olması açısından ben Parametrelerinizi kaldırıldı ve işlevinde bir döngü uygulamak yoktu, ama sen prensibini görebilirsiniz.

Kullanımı:

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

Bir imlecin kullanılmasının, geçici bir tablo kullanmaktan ziyade kaynak yoğunluğu (daha yavaş) olacağı varsayılmaktadır. Doğrumuyum? Bu işlevin sonuçlarını gruplandırmam gerekiyor. Bu önerilerinizi değiştirir mi? – craig

+0

İmleçle ilgili olarak, evet performans açısından çok iyi olmadıklarına inanıyorum, bu yüzden Tony'nin bahsettiği gibi TOPLU TOPLAMA yapmak daha hızlı olur ve daha sonra dizi üzerinde yineleyin. Bu, uğraştığınız satırların sayısına ve diğer performans değerlendirmelerine bağlı olacaktır. Sonuçları gruplandırmaya gelince, emin değilim, ama geçici bir tablonun her durumda boru hattından daha verimli olacağını düşünüyorum. Daha fazla araştırma öneririm (ya da daha iyisi, deneyler). Soruyu http://asktom.oracle.com adresinden rica ediyorum. –

+0

Lütfen downvote'u açıklayın. –

3

size SEÇ değişebilir kerede bütün tablo dönmek için:

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

Bu aşırı büyük olmayan sonuçlar için sadece tavsiye edilir çünkü hepsi iade edilmeden önce bellekte biriktirilmek zorundadır; Aksi takdirde, Charles tarafından önerilen veya REF CURSOR döndüren pipelined işlevi düşünün.

+0

İçgörü için teşekkürler. – 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

Bu işlevi çağırmak için sözdizimi nedir? 'TABLE (TEST.GET_UPS (...)) 'dan * seçin *? – craig