2014-12-09 5 views
6

Wir müssen ein Umschreiben der Abfrage mit einer Bindevariablen implementieren, da wir den Quellcode der Webanwendung nicht ändern können. Beispiel:Wie verwende ich Oracle DBMS_ADVANCED_REWRITE mit Bindevariable?

BEGIN 
    SYS.DBMS_ADVANCED_REWRITE.declare_rewrite_equivalence (
    name    => 'test_rewrite2', 
    source_stmt  => 'select COUNT(*) from ViewX where columnA = :1', 
    destination_stmt => 'select COUNT(*) from ViewY where columnA = :1', 
    validate   => FALSE, 
    rewrite_mode  => 'recursive');  
END; 

Der obige Befehl in Fehlern führen wird, weil es eine Variable binden ist:

30353. 00000 - "expression not supported for query rewrite" 
*Cause: The SELECT clause referenced UID, USER, ROWNUM, SYSDATE, 
      CURRENT_TIMESTAMP, MAXVALUE, a sequence number, a bind variable, 
      correlation variable, a set result, a trigger return variable, a 
      parallel table queue column, collection iterator, a non-deterministic 
      date format token RR, etc. 
*Action: Remove the offending expression or disable the REWRITE option on 
      the materialized view. 

ich here lese, dass es eine Arbeit um, aber ich kann einfach nicht das Dokument überall online finden.

Können Sie mir bitte sagen, worum es bei der Arbeit geht?

Antwort

1

Sie können die Bindeparameter nicht angeben, aber es sollte bereits funktionieren, wie Sie möchten. Der Schlüssel ist der recursive Parameter, den Sie als mode übergeben haben. Der Modus recursive und general fängt alle Anweisungen ab, die die Tabelle (oder Ansicht) betreffen, ignoriert den Filter und wandelt sie in die zweite Tabelle (oder Ansicht) um. Anpassung der Filterbedingung aus Ihrer ursprünglichen Anweisung. (Wenn Sie es als TEXT_MATCH definiert hätten, hätte er das Vorhandensein des gleichen Filters in der Ausgangs- und Ziel Anweisung überprüft, um die Umwandlung auszulösen.)

Im Beispiel unten ein, dass selbst wenn wir don sieht Definieren Sie keine Bindungsbedingung, der Filter id = 2 wird trotzdem angewendet; mit anderen Worten wandelt es tatsächlich die SELECT * FROM A1 where id = 2 in SELECT * FROM A2 where id = 2

set LINESIZE 300 

drop table A1; 
drop view A2; 
drop index A1_IDX; 
EXEC SYS.DBMS_ADVANCED_REWRITE.drop_rewrite_equivalence (name => 'test_rewrite'); 

create table A1 (id number, name varchar2(20)); 

insert into A1 values(1, 'hello world'); 
insert into A1 values(2, 'hola mundo'); 

create index A1_IDX on A1(id); 

select * from A1; 

ALTER SESSION SET QUERY_REWRITE_INTEGRITY = TRUSTED; 

CREATE OR REPLACE VIEW A2 AS 
SELECT id, 
     INITCAP(name) AS name 
FROM A1 
ORDER BY id desc; 


BEGIN 
    SYS.DBMS_ADVANCED_REWRITE.declare_rewrite_equivalence (
    name    => 'test_rewrite', 
    source_stmt  => 'SELECT * FROM A1', 
    destination_stmt => 'SELECT * FROM A2', 
    validate   => FALSE, 
    rewrite_mode  => 'recursive'); 
END; 
/


select * from A1; 

     ID NAME    
---------- -------------------- 
     2 Hola Mundo   
     1 Hello World   




select * from A1 where id = 2; 


     ID NAME    
---------- -------------------- 
     2 Hola Mundo  


explain plan for 
select * from A1 where id = 2; 

select * from table(dbms_xplan.display); 


PLAN_TABLE_OUTPUT                                                                       
---------------------------------------------------------------------------------------- 
Plan hash value: 1034670462                                                                     

----------------------------------------------------------------------------------------                                                      
| Id | Operation      | Name | Rows | Bytes | Cost (%CPU)| Time  |                                                      
----------------------------------------------------------------------------------------                                                      
| 0 | SELECT STATEMENT    |  |  1 | 25 |  2 (0)| 00:00:01 |                                                      
| 1 | VIEW       | A2  |  1 | 25 |  2 (0)| 00:00:01 |                                                      
| 2 | TABLE ACCESS BY INDEX ROWID | A1  |  1 | 25 |  2 (0)| 00:00:01 |                                                      
|* 3 | INDEX RANGE SCAN DESCENDING| A1_IDX |  1 |  |  1 (0)| 00:00:01 |                                                      
----------------------------------------------------------------------------------------                                                      


PLAN_TABLE_OUTPUT                                                                       
--------------------------------------------------- 
Predicate Information (identified by operation id):                                                               
---------------------------------------------------                                                               

    3 - access("ID"=2)                                                                      

Note                                                                           
-----                                                                          
    - dynamic sampling used for this statement (level=2)                                                              
    - automatic DOP: Computed Degree of Parallelism is 1 because of parallel threshold                                                      

20 rows selected 

Wie Sie

  1. der Motor
  2. auf Hinzu kommt, dass die Transformation der Transformation und der Rückkehr des gefilterten Ergebnis transparent sehen bewirbt auf den Filter angewendet wird. Der Filter wird korrekt in die Quelltabelle "geschoben", um die Werte aus A1 zu extrahieren. Es extrahiert nicht blind alle Werte von A2 und wendet dann den Filter an, so dass die Leistung erhalten bleibt.