2011-09-07 6 views
12
SELECT COUNT (*) 
    FROM rps2_workflow 
WHERE  workflow_added > TO_DATE ('01.09.2011', 'dd.mm.yyyy') 
     AND workflow_finished < TO_DATE ('wtf', 'dd.mm.yyyy') 
     AND workflow_status IN (7, 12, 17) 
     AND workflow_worker = 159 

Spodziewam ta kwerenda się niepowodzeniem, z powodu nieprawidłowej daty, ale zwraca 0nieoczekiwany sukces zapytania

Plan dla tego zapytania wynika, że ​​w dniu 8 kroku nieważna klauzula jest przetwarzane:

8 TABLE ACCESS BY INDEX ROWID TABLE RPS2.RPS2_WORKFLOW Object Instance: 1 Filter Predicates: ("WORKFLOW_STATUS"=7 OR "WORKFLOW_STATUS"=12 OR "WORKFLOW_STATUS"=17) AND SYS_EXTRACT_UTC("WORKFLOW_FINISHED")<SYS_EXTRACT_UTC(TO_DATE('wtf','dd.mm.yyyy')) Cost: 11 Bytes: 33 Cardinality: 1 CPU Cost: 8 M IO Cost: 10 Time: 1      

Gdybyśmy wykomentuj AND workflow_status IN (7, 12, 17) warunku - wtedy expectedly otrzymujemy ORA-01858: a non-numeric character was found where a numeric was expected

Gdybyśmy wykomentuj AND workflow_finished < TO_DATE ('wtf', 'dd.mm.yyyy') następnie otrzymujemy ilość rekordów, które pasują do tych warunków (> 0)

Jak to jest możliwe?

UPD:

Podpowiedź /*+no_index(rps2_workflow) */ niczego nie zmienia (podczas gdy w planie widzimy, że jest wykonywana FullScan)

SELECT STATEMENT ALL_ROWSCost: 254 Bytes: 31 Cardinality: 1 CPU Cost: 34 M IO Cost: 248 Time: 4  
2 SORT AGGREGATE Bytes: 31 Cardinality: 1  
    1 TABLE ACCESS FULL TABLE RPS2.RPS2_WORKFLOW Object Instance: 1 Filter Predicates: "WORKFLOW_WORKER"=159 AND ("WORKFLOW_STATUS"=7 OR "WORKFLOW_STATUS"=12 OR "WORKFLOW_STATUS"=17) AND SYS_EXTRACT_UTC("WORKFLOW_ADDED")>SYS_EXTRACT_UTC(TIMESTAMP' 2011-09-01 00:00:00') AND SYS_EXTRACT_UTC("WORKFLOW_FINISHED")<SYS_EXTRACT_UTC(TO_DATE('wtf','dd.mm.yyyy')) Cost: 254 Bytes: 31 Cardinality: 1 CPU Cost: 34 M IO Cost: 248 Time: 4 
+0

@BoltClock: aw, nie można umieścić sql na końcu listy tagów: -S Problem jest specyficzny dla oracle, a nie tylko ogólne pytanie sql – zerkms

+0

Zgaduję, że optymalizator nie znalazł rekordów (przy użyciu indeksów) dla pracownika 159 ze statusem 7, 12 lub 17, więc nie zawracało sobie głowy oceną reszty zapytania. Po usunięciu sprawdzania stanu niektóre rekordy zostaną znalezione, więc musi ocenić funkcję TO_DATE i powoduje błąd. Trudno powiedzieć na pewno, co robi optymalizator zapytań ... – Sparky

+0

@Sparky: spójrz na ostatni akapit - jeśli usuniemy "nieprawidłowy" fragment zapytania - zwróci on wiersze. Pomyślałem tak za chwilę, ale ** są ** rekordy o określonych statusach – zerkms

Odpowiedz

3

prawdopodobnie uznał, że każdy rekord spełniający wszystkie pozostałe warunki mają NULLworkflow_finished pole.

Wszystko w porównaniu do NULL jest nieznane, więc nie trzeba oceniać drugiego argumentu.

+1

+1 Tylko pomniejszy punkt: wszystko w porównaniu do NULL jest nieznane, a nie fałszywe, choć nie ma znaczenia tutaj. –

7

Jeśli optymalizator zdecyduje, że nie trzeba ocenia funkcję, nie będzie, więc funkcja nigdy nie wyrzuci wyjątków:

select 1 from dual where 1 = 1 OR to_date('asdasdasd','asdasdasdas') > sysdate ; 

     1 
---------- 
     1 

Funkcja podnosi wyjątek tylko wtedy, gdy rzeczywiście zostanie ocenione:

SQL> select 1 from dual where 1 = 1 AND to_date('asdasd','asdas') > sysdate ; 
select 1 from dual where 1 = 1 AND to_date('asdasd','asdas') > sysdate 
                * 
ERROR at line 1: 
ORA-01821: date format not recognized 

Jednak jeśli parser może zdecydować statycznie że zapytanie jest nieważne - ponieważ funkcja ma niewłaściwy typ argumentów lub kwerenda zawiera nieprawidłowe typy, wówczas parser zgłosi wyjątek przed optymalizator dostaje huśtawka na to:

SQL> select 1 from dual where 1 = 1 or to_date('asdasdasd',0) > sysdate ; 
select 1 from dual where 1 = 1 or to_date('asdasdasd',0) > sysdate 
                 * 
ERROR at line 1: 
ORA-00932: inconsistent datatypes: expected DATE got NUMBER 


SQL> select 1 from dual where 1 = 1 or to_date('asdasdasd','asdasdasdas') > 42 ; 
select 1 from dual where 1 = 1 or to_date('asdasdasd','asdasdasdas') > 42 
                     * 
ERROR at line 1: 
ORA-00932: inconsistent datatypes: expected DATE got NUMBER 
+0

Nawet jeśli masz absolutną rację - to nie jest odpowiedź. Ponieważ problem był nieco głębszy (nie na poziomie predykatu, ale na poziomie operandu). A alexisdm odgadł to poprawnie. +1 i tak – zerkms

+0

Ah, nie przeczytałem wszystkich "czytaj więcej" komentarzy przed odpowiedzią :) –

+0

, ale mimo wszystko wykonałeś świetną pracę. Te informacje z pewnością będą przydatne dla każdego dalszego czytelnika. Jeśli alexisdm nie udzieli odpowiedzi - sprawdzę twoje (i dodam sprawę spowodowało to "dziwne" zachowanie) – zerkms