2012-01-26 12 views
12

içinde parametreli görünümler oluşturma İç içe geçirme ve sol birleştirmeyle büyük bir sorgum var ve uygulamadan çalıştırmamak için dışarıdan bir görünüm oluşturmak için Ineed'im var. Sorun, her bir istek için ön uçtan değişeceğinden, tarih aralığı ve giriş parametreleri olarak diğer bazı alanlara ihtiyacım var. Sadece baktım ve parametreli görünümler için SYS_CONTEXT kullanarak atıfta bazı mesajlar gördüm ve tam olarak örneğin 2 parametre - fromdate, todate ve uygulamadan görünümü nasıl çağırmak için görünüm oluşturmayı bilmeniz gerekir.oracle11g

Sadece bilgi için uygulamayı geliştirmek için grails/groovy kullanıyorum. ve burada dışarı görünümü oluşturmak istediğiniz sorgusudur ..

select 
    d.dateInRange as dateval, 
    eventdesc, 
    nvl(td.dist_ucnt, 0) as dist_ucnt 
from (
    select 
     to_date(fromdate,'dd-mon-yyyy') + rownum - 1 as dateInRange 
    from all_objects 
    where rownum <= to_date(fromdate,'dd-mon-yyyy') - to_date(todate,'dd-mon-yyyy') + 1 
) d 
left join (
    select 
     to_char(user_transaction.transdate,'dd-mon-yyyy') as currentdate, 
     count(distinct(grauser_id)) as dist_ucnt, 
     eventdesc 
    from 
     gratransaction, user_transaction 
    where gratransaction.id = user_transaction.trans_id and 
    user_transaction.transdate between to_date(fromdate,'dd-mon-yyyy') and to_date(todate,'dd-mon-yyyy') 
    group by to_char(user_transaction.transdate, 'dd-mon-yyyy'), eventdesc 
) td on td.currentdate = d.dateInRange order by d.dateInRange asc 

cevap

14

Bağlam yöntemi burada açıklanmaktadır: http://docs.oracle.com/cd/B28359_01/network.111/b28531/app_context.htm

örn.

SELECT bla FROM mytable 
WHERE mydate 
    BETWEEN TO_DATE(
      SYS_CONTEXT('dates_ctx', 'd1') 
      ,'DD-MON-YYYY') 
     AND TO_DATE(
      SYS_CONTEXT('dates_ctx', 'd2') 
      ,'DD-MON-YYYY'); 

Bunun avantajı:

BEGIN set_dates_ctx_pkg.set(mydate1, mydate2); END; 
/
Sonra

, parametreleri sorgulamak: (yukarıdaki bağlantıdan uyarlanan örnek) Sonra

CREATE CONTEXT dates_ctx USING set_dates_ctx_pkg; 

CREATE OR REPLACE PACKAGE set_dates_ctx_pkg IS 
    PROCEDURE set(d1 in date, d2 in date); 
END; 
/

CREATE OR REPLACE PACKAGE BODY set_dates_ctx_pkg IS 
    PROCEDURE set(d1 in date, d2 in date) IS 
    BEGIN 
    DBMS_SESSION.SET_CONTEXT('dates_ctx', 'd1', TO_CHAR(d1,'DD-MON-YYYY')); 
    DBMS_SESSION.SET_CONTEXT('dates_ctx', 'd2', TO_CHAR(d2,'DD-MON-YYYY')); 
    END; 
END; 
/

, ile uygulama tarihleri ​​ayarlayın yaklaşım, çok sorgu dostu olması; Çalışma zamanında DDL veya DML içermez ve bu nedenle endişelenecek bir işlem yoktur; ve çok hızlı çünkü SQL - PL/SQL içerik anahtarı içermiyor.

Alternatif olarak:

bağlam yöntemi ve John'un paket değişkenleri yöntemi sizin için mümkün değilse, başka bir (bir tabloya parametreleri eklemektir örneğin küresel bir geçici tablo, sen sorgu çalıştırıyorsanız aynı seansta), daha sonra bu tabloya görünümden katılın. Downside, sorguyu çalıştırmak istediğinizde parametreleri eklemek için bazı DML'yi çalıştırdığınızdan emin olmanız gerekiyor.

+0

biz fonksiyonların işlemlerini kullanamazsınız, ancak çözümler burada –

+3

önerilen seçeneklerden içine bakarak ve denediğiniz olacağını * * Eğer prosedürler, fonksiyonlar kullanamıyorum neden ya paketler? Oracle kullanıyorsanız, bunları önlemek için iyi bir sebep yoktur. –

+0

Bazı insanlar salt okuma veri tabanlarına erişimini. –

4

tek yolu parametrelerinin değerlerini ayarlar bir paket oluşturmak ve çağrılabilir işlevlere sahip olan bir görünümde parametreleri kullanmak için bu değerleri almak için. Örneğin:

create or replace package MYVIEW_PKG as 
    procedure SET_VALUES(FROMDATE date, TODATE date); 

    function GET_FROMDATE 
    return date; 

    function GET_TODATE 
    return date; 
end MYVIEW_PKG; 

create or replace package body MYVIEW_PKG as 
    G_FROM_DATE date; 
    G_TO_DATE  date; 

    procedure SET_VALUES(P_FROMDATE date, P_TODATE date) as 
    begin 
    G_FROM_DATE := P_FROMDATE; 
    G_TO_DATE := P_TODATE; 
    end; 

    function GET_FROMDATE 
    return date is 
    begin 
    return G_FROM_DATE; 
    end; 

    function GET_TODATE 
    return date is 
    begin 
    return G_TO_DATE; 
    end; 
end MYVIEW_PKG; 

Sonra görünümü dolayısıyla oluşturulabilir:

create or replace view myview as 
    select 
     d.dateInRange as dateval, 
     eventdesc, 
     nvl(td.dist_ucnt, 0) as dist_ucnt 
    from (
     select 
      MYVIEW_PKG.GET_FROMDATE + rownum - 1 as dateInRange 
     from all_objects 
     where rownum <= MYVIEW_PKG.GET_FROMDATE - MYVIEW_PKG.GET_TODATE + 1 
    ) d 
    left join (
     select 
      to_char(user_transaction.transdate,'dd-mon-yyyy') as currentdate, 
      count(distinct(grauser_id)) as dist_ucnt, 
      eventdesc 
     from 
      gratransaction, user_transaction 
     where gratransaction.id = user_transaction.trans_id and 
     user_transaction.transdate between MYVIEW_PKG.GET_FROMDATE and MYVIEW_PKG.GET_TODATE 
     group by to_char(user_transaction.transdate, 'dd-mon-yyyy'), eventdesc 
    ) td on td.currentdate = d.dateInRange order by d.dateInRange asc; 

Ve ilk değerleri ayarlamanız gerekir çalıştırmak için: o zaman

exec MYVIEW_PKG.SET_VALUES(trunc(sysdate)-1,trunc(sysdate)); 

Ve kullanacak çağrıları Bu değerler:

select * from myview; 
+0

hmm ... performansı hakkında emin değilim ...Bu yaklaşımın, bu uygulamada izin verilmeyen işlevlere/paketlere kesinlikle ihtiyaç duyacağı anlaşılıyor. Ben çevrimiçi bazı çözümler gördün ama bunların çoğu işlevlere sahiptir/prosedürler –

5

Bu sinir bozucu Oracle dezavantajı için yeni bir çözüm bulduk. Bu

create or replace package pkg_utl 
as 
    type test_record is record (field1 number, field2 number, ret_prm_date date); 
    type test_table is table of test_record; 
    function get_test_table(prm_date date) return test_table pipelined; 
end; 
/

create or replace package body pkg_utl 
as 
    function get_test_table(prm_date date) return test_table pipelined 
    is 
    begin 
    for item in (
     select 1, 2, prm_date 
     from dual 
    ) loop 
     pipe row (item); 
    end loop; 
    return; 
    end get_test_table; 
end; 
/

gibi hala bir paket gerektirir, ama en azından ben daha rahat bir şekilde kullanabilirsiniz:

select * 
from table(pkg_utl.get_test_table(sysdate)) 

i

+0

tam olarak nasıl bu adres gereksinimi bir görünüme argümanları itmek için muktedir geliyor? Örnek sorgunuz hala görünümde ("sysdate") kodlanmış bir parametreye sahiptir. Sadece sysdate'ı doğrudan bir pakete gerek kalmadan görünümde kullanabilirsiniz. –

+0

Merhaba, Jeffrey. sysdate sadece bir örnektir - herhangi bir değer koyabilirsiniz. Burada anahtar şey ama harici parametre (prm_date) ile, sadece bir görünümü gibi (bizim örneğimizde öyle "ikili dan 1, 2, prm_date seçin") Sorgunuzla yeniden kullanabilirsiniz olmasıdır. – Neco

+0

Yani bir pipelined işlevi içinde bir sorgu ile tamamen görünümünü değiştirerek öneriyorsun? –