2012-01-26 10 views
12

Mam dużą kwerendę z zagnieżdżaniem i łączeniem w lewo i Ineed, aby utworzyć widok z niego, tak aby nie uruchamiać go z aplikacji. Problem polega na tym, że potrzebuję zakresu dat i innych pól jako parametrów wejściowych, ponieważ będzie on różnił się od interfejsu dla każdego żądania. Właśnie podniosłem wzrok i zobaczyłem kilka postów odnoszących się do użycia SYS_CONTEXT do sparametryzowanych widoków i muszę dokładnie wiedzieć, jak utworzyć widok na przykład z 2 parametrami - fromdate, todate i jak wywołuję widok z aplikacji.tworzenie sparametryzowanych widoków w oracle11g

Tylko dla informacji używam grails/groovy do rozwijania aplikacji. i tutaj jest kwerenda Chcę utworzyć widok z ..

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 

Odpowiedz

14

Sposób kontekstu jest opisany tutaj: http://docs.oracle.com/cd/B28359_01/network.111/b28531/app_context.htm

np. (Przykład dostosowane z powyższego linku)

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; 
/

Następnie ustawić daty w aplikacji z:

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

Następnie kwerendy parametry z:

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'); 

Zaletą tego podejście to jest bardzo przyjazne dla zapytań; nie wymaga DDL ani DML w czasie wykonywania, dlatego nie trzeba martwić się o transakcje; i jest bardzo szybki, ponieważ nie wymaga przełączania kontekstu SQL-PL/SQL.

Alternatywnie:

Jeśli metoda kontekst i Jana zmienne pakietów metody nie są możliwe dla ciebie, drugi jest dodanie parametrów do tabeli (np globalną tabeli tymczasowej, jeśli używasz kwerendę w w tej samej sesji), a następnie dołącz do tej tabeli z widoku. Minusem jest to, że teraz musisz upewnić się, że uruchomiłeś jakiś DML, aby wstawić parametry, gdy chcesz uruchomić zapytanie.

+0

nie możemy używać procedur funkcji, ale chciałbym zajrzeć do opcji i wypróbować proponowane tutaj rozwiązania –

+3

* Dlaczego * nie możesz użyć procedur, funkcji lub pakiety? Jeśli korzystasz z Oracle, nie ma powodu, aby ich unikać. –

+0

Niektóre osoby mają dostęp tylko do odczytu do baz danych. –

4

używać parametrów w widoku jednym ze sposobów jest stworzenie pakietu, który będzie ustawić wartości parametrów i mieć swoich funkcji, które mogą być wywoływane aby uzyskać te wartości. Na przykład:

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; 

Wtedy twój widok można utworzyć w następujący sposób:

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; 

I aby go uruchomić należy ustawić wartości:

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

a następnie wywołuje się użyje te wartości:

select * from myview; 
+0

hmm ...Wygląda na to, że takie podejście na pewno będzie wymagało funkcji/pakietów ... które nie są dozwolone w tej implementacji. Widziałem niektóre rozwiązania w Internecie, ale większość z nich ma funkcje/procedury –

5

Właśnie zastosowałem obejście tego irytującego problemu Oracle. Podoba Ci się to

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; 
/

nadal wymaga pakietu, ale przynajmniej mogę używać go w więcej Wyjątkowo sposób:

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

nie jestem pewien, o wydajności ...

+0

Jak dokładnie odpowiada to wymaganiom, aby móc przekazywać argumenty do widoku? Twoje zapytanie próbne nadal ma parametr zakodowany w obrębie widoku ('sysdate'). Możesz równie dobrze użyć 'sysdate' bezpośrednio w widoku bez potrzeby posiadania pakietu. –

+0

Cześć, Jeffrey. sysdate to tylko przykład - możesz tam umieścić dowolną wartość. Kluczową sprawą jest to, że możesz ponownie użyć zapytania (w moim przykładzie jest to "wybierz 1, 2, prm_date z podwójnego"), podobnie jak widok, ale z zewnętrznym parametrem (prm_date). – Neco

+0

Proponujesz zastąpienie widoku całkowicie kwerendą wewnątrz funkcji potokowej? –

Powiązane problemy