2011-09-21 34 views
32

Quindi sono abbastanza sicuro che Oracle lo supporti, quindi non ho idea di cosa sto facendo male. Questo codice funziona:Oracle - Come creare una vista materializzata con FAST REFRESH e JOINS

CREATE MATERIALIZED VIEW MV_Test 
    NOLOGGING 
    CACHE 
    BUILD IMMEDIATE 
    REFRESH FAST ON COMMIT 
    AS 
    SELECT V.* FROM TPM_PROJECTVERSION V; 

Se posso aggiungere in un join, si rompe:

CREATE MATERIALIZED VIEW MV_Test 
    NOLOGGING 
    CACHE 
    BUILD IMMEDIATE 
    REFRESH FAST ON COMMIT 
    AS 
    SELECT V.*, P.* FROM TPM_PROJECTVERSION V 
    INNER JOIN TPM_PROJECT P ON P.PROJECTID = V.PROJECTID 

Ora ottengo l'errore:

ORA-12054: non può impostare l'ON COMMIT attributo di aggiornamento per la vista materializzata

Ho creato registri delle viste materializzati sia su TPM_PROJECT che su TPM_PROJECTVERSION. TPM_PROJECT ha una chiave primaria di PROJECTID e TPM_PROJECTVERSION ha una chiave primaria composta di (PROJECTID, VERSIONID). Qual è il trucco per questo? Sto scavando attraverso i manuali Oracle senza alcun risultato. Grazie!

+2

Hai provato 'DBMS_MVIEW.EXPLAIN_MVIEW'? Dovrebbe mostrarti le opzioni disponibili per la vista? – a1ex07

+0

La prima cosa che farei è perdere i * nella clausola select. Non sono sicuro di come la vista gestirà i nomi di colonna duplicati – Phil

+0

Sì, ho cercato di capire come eseguire DBMS_MVIEW.EXPLAIN_MVIEW ma non ho ancora funzionato. Scusa, sono molto nuovo per Oracle. –

risposta

42

per cominciare, dal Oracle Database Data Warehousing Guide:

Restrictions on Fast Refresh on Materialized Views with Joins Only

...

  • Rowids of all the tables in the FROM list must appear in the SELECT list of the query.

Ciò significa che la sua dichiarazione dovrà essere simile a questa:

CREATE MATERIALIZED VIEW MV_Test 
    NOLOGGING 
    CACHE 
    BUILD IMMEDIATE 
    REFRESH FAST ON COMMIT 
    AS 
    SELECT V.*, P.*, V.ROWID as V_ROWID, P.ROWID as P_ROWID 
    FROM TPM_PROJECTVERSION V, 
     TPM_PROJECT P 
    WHERE P.PROJECTID = V.PROJECTID 

Un altro aspetto fondamentale da notare è che il vostro i registri di visualizzazione materializzati devono essere creati come with rowid.

Qui di seguito è uno scenario di test funzionale:

CREATE TABLE foo(foo NUMBER, CONSTRAINT foo_pk PRIMARY KEY(foo)); 

CREATE MATERIALIZED VIEW LOG ON foo WITH ROWID; 

CREATE TABLE bar(foo NUMBER, bar NUMBER, CONSTRAINT bar_pk PRIMARY KEY(foo, bar)); 

CREATE MATERIALIZED VIEW LOG ON bar WITH ROWID; 

CREATE MATERIALIZED VIEW foo_bar 
    NOLOGGING 
    CACHE 
    BUILD IMMEDIATE 
    REFRESH FAST ON COMMIT AS SELECT foo.foo, 
            bar.bar, 
            foo.ROWID AS foo_rowid, 
            bar.ROWID AS bar_rowid 
           FROM foo, bar 
           WHERE foo.foo = bar.foo; 
+2

Uggghhhh santo schifo grazie! FINALMENTE ha funzionato. In realtà non ottengo davvero il punto di vista materializzato in Oracle. Sono limitati al punto in cui non sono veramente utili a nessuno.Mi chiedo se le viste indicizzate in MS SQL siano meglio. –

+1

Le viste indicizzate in MS SQL sono diverse: vengono sempre aggiornate immediatamente, ma esistono alcune limitazioni piuttosto gravi, ad esempio senza sottocommissioni, senza join esterni, senza viste indicizzate nidificate, senza funzioni non deterministiche, ecc. Vedi https://docs.microsoft.com/en-us/sql/relational-databases/views/create-indexed-views – DaveBoltman

5

Hai provato senza l'ANSI?

CREATE MATERIALIZED VIEW MV_Test 
    NOLOGGING 
    CACHE 
    BUILD IMMEDIATE 
    REFRESH FAST ON COMMIT 
    AS 
SELECT V.*, P.* FROM TPM_PROJECTVERSION V,TPM_PROJECT P 
WHERE P.PROJECTID = V.PROJECTID 
+1

Hmm questo sembra funzionare magicamente meglio. Tuttavia, ora ricevo un errore sul RIFERIMENTO VELOCE. Se lo cambio in REFRESH COMPLETE, crea la vista. Questo potrebbe rendere alcuni aggiornamenti molto lenti se deve eseguire manualmente l'intera query ogni volta che una delle tabelle sottostanti viene aggiornata. Ho pensato che FAST REFRESH fosse permesso fintanto che ci fossero registri di visualizzazione materializzati per ogni tavolo. –

+0

In effetti, qualche tempo fa ho creato un caso per Oracle. Oracle considera questo solo come una "mancanza di documentazione" non come un bug! Quindi, la vecchia sintassi di join Oracle è ancora richiesta. –

3

Si otterrà l'errore sul REFRESH_FAST, se non si crea vista materializzata registri per la tabella principale (s) la query si riferisce. Se qualcuno non ha familiarità con le viste materializzate o lo usa per la prima volta, il modo migliore è usare oracle sqldeveloper e inserire graficamente le opzioni, e gli errori forniscono anche molto più senso.

1

I controlli chiave per aggiornamento rapido include quanto segue:

1) An Oracle materialized view log must be present for each base table. 
2) The RowIDs of all the base tables must appear in the SELECT list of the MVIEW query definition. 
3) If there are outer joins, unique constraints must be placed on the join columns of the inner table. 

No 3 è facile perdere e vale la pena sottolineare qui

Problemi correlati