Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Czy instrukcja CASE i DECODE są równoważne?

Krótka odpowiedź, nie.

Nieco dłuższa odpowiedź jest prawie.

Tylko pojawia się że wynik uzyskany z każdego stwierdzenia jest identyczny. Jeśli użyjemy funkcji DUMP do oceny zwróconych typów danych, zobaczysz, co mam na myśli:

SQL> select dump(case 1 when 2 then null else 0 end) as simple_case
  2       , dump(case when 1 = 2 then null else 0 end) as searched_case
  3       , dump(decode(1, 2, null, 0)) as decode
  4    from dual;

SIMPLE_CASE        SEARCHED_CASE      DECODE
------------------ ------------------ -----------------
Typ=2 Len=1: 128   Typ=2 Len=1: 128   Typ=1 Len=1: 48

Skrzypce SQL

Możesz zobaczyć, że typ danych DECODE to 1, podczas gdy dwie instrukcje CASE "zwracają" typ danych 2. Korzystając z podsumowania typów danych Oracle, DECODE zwraca VARCHAR2 (typ danych 1), podczas gdy instrukcje CASE "zwracają " liczby (typ danych 2).

Zakładam, że dzieje się tak, ponieważ, jak sugerują nazwy, DECODE to funkcja a CASE nie, co oznacza, że ​​zostały wewnętrznie zaimplementowane inaczej. Nie ma prawdziwego sposobu, aby to udowodnić.

Możesz pomyśleć, że to tak naprawdę na nic nie wpływa. Jeśli potrzebujesz liczby, Oracle niejawnie skonwertuje znak na liczbę zgodnie z regułami niejawnej konwersji, prawda? To też nie jest prawdą, nie będzie działać w UNION, tak jak typy danych mają być identyczne; Oracle nie dokona żadnej niejawnej konwersji, aby ułatwić Ci pracę. Po drugie, oto co Oracle mówi o konwersji niejawnej:

Oracle zaleca, aby określić jawne konwersje, zamiast polegać na niejawnych lub automatycznych konwersjach, z następujących powodów:

  • Instrukcje SQL są łatwiejsze do zrozumienia, gdy używasz jawnych funkcji konwersji typów danych.

  • Niejawna konwersja typu danych może mieć negatywny wpływ na wydajność, zwłaszcza jeśli typ danych wartości kolumny jest konwertowany na wartość stałą, a nie na odwrót.

  • Konwersja niejawna zależy od kontekstu, w którym występuje i może nie działać w ten sam sposób w każdym przypadku. Na przykład niejawna konwersja z wartości daty i godziny na wartość VARCHAR2 może zwrócić nieoczekiwany rok w zależności od wartości parametru NLS_DATE_FORMAT.

  • Algorytmy konwersji niejawnej mogą ulec zmianie w różnych wersjach oprogramowania i produktów Oracle. Zachowanie jawnych konwersji jest bardziej przewidywalne.

To nie jest ładna lista; ale przedostatni punkt ładnie prowadzi mnie na randki. Jeśli weźmiemy poprzednie zapytanie i przekonwertujemy je na takie, które zamiast tego używa daty:

select case sysdate when trunc(sysdate) then null 
                    else sysdate 
       end as simple_case
     , case when sysdate = trunc(sysdate) then null 
            else sysdate 
       end as searched_case
     , decode(sysdate, trunc(sysdate), null, sysdate) as decode
  from dual;

Ponownie, używając DUMP w tym zapytaniu, instrukcje CASE zwracają typ danych 12, DATE. DECODE przekonwertował sysdate w VARCHAR2.

SQL> select dump(case sysdate when trunc(sysdate) then null
  2                           else sysdate
  3              end) as simple_case
  4       , dump(case when sysdate = trunc(sysdate) then null
  5                   else sysdate
  6              end) as searched_case
  7       , dump(decode(sysdate, trunc(sysdate), null, sysdate)) as decode
  8    from dual;

SIMPLE_CASE          
---------------------------------- 
Typ=12 Len=7: 120,112,12,4,22,18,7 
SEARCHED_CASE
---------------------------------- 
Typ=12 Len=7: 120,112,12,4,22,18,7
DECODE
---------------------------------- 
Typ=1 Len=19: 50,48,49,50,45,49,50,45,48,52,32,50,49,58,49,55,58,48,54

Skrzypce SQL

Zauważ (w SQL Fiddle), że DATE została przekonwertowana na znak przy użyciu sesji NLS_DATE_FORMAT.

Posiadanie daty, która została niejawnie przekonwertowana na VARCHAR2 może powodować problemy. Jeśli zamierzasz użyć TO_CHAR, aby przekonwertować datę na znak, Twoje zapytanie zostanie przerwane tam, gdzie się tego nie spodziewasz.

SQL> select to_char( decode( sysdate
  2                         , trunc(sysdate), null
  3                         , sysdate )
  4                 , 'yyyy-mm-dd') as to_char
  5    from dual;
select to_char( decode( sysdate
                *
ERROR at line 1:
ORA-01722: invalid number

Skrzypce SQL

Podobnie, arytmetyka dat już nie działa:

SQL>
SQL>
SQL> select decode(sysdate, trunc(sysdate), null, sysdate) + 1 as decode
  2    from dual;
select decode(sysdate, trunc(sysdate), null, sysdate) + 1 as decode
       *
ERROR at line 1:
ORA-01722: invalid number

Skrzypce SQL

Co ciekawe DECODE konwertuje wyrażenie na VARCHAR2 tylko wtedy, gdy jeden z możliwych wyników jest NULL. Jeśli domyślna wartość to NULL, to tak się nie dzieje. Na przykład:

SQL> select decode(sysdate, sysdate, sysdate, null) as decode
  2    from dual;

DECODE
-------------------
2012-12-04 21:18:32

SQL> select dump(decode(sysdate, sysdate, sysdate, null)) as decode
  2    from dual;

DECODE
------------------------------------------    
Typ=13 Len=8: 220,7,12,4,21,18,32,0

Skrzypce SQL

Zauważ, że DECODE zwrócił typ danych 13. Nie jest to udokumentowane, ale zakładam, że jest to typ daty, jak działa arytmetyka dat itp.

Krótko mówiąc, unikaj DEKODOWANIA, jeśli możesz; niekoniecznie otrzymasz oczekiwane typy danych. Cytując Toma Kyte'a:

Dekodowanie jest nieco niejasne -- CASE jest bardzo jasne. Rzeczy, które są łatwe do zrobienia w dekodowaniu, są łatwe do zrobienia w CASE, rzeczy, które są trudne lub prawie niemożliwe do zrobienia za pomocą dekodowania, są łatwe do zrobienia w CASE. CASE logicznie wygrywa.

Aby być kompletnym, są dwa funkcjonalne różnice między DECODE i CASE.

  1. DECODE nie może być używany w PL/SQL.
  2. CASE nie może być używany do bezpośredniego porównywania wartości null

    SQL> select case null when null then null else 1 end as case1
      2        , case when null is null then null else 1 end as case2
      3        , decode(null, null, null, 1) as decode
      4    from dual
      5         ;
    
         CASE1      CASE2 DECODE
    ---------- ---------- ------
             1
    

    Skrzypce SQL



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Obsługa współbieżnych aktualizacji w trybie hibernacji

  2. Wyszukaj, czy liczba jest zawarta w wyrażeniu takim jak:1-3,5,10-15,20

  3. Jak można stwierdzić, czy używany jest pakiet, procedura lub funkcja PL/SQL?

  4. Plany wykonania Oracle przy użyciu operatora LIKE z funkcją DETERMINISTIC

  5. Jak przeprowadzić migrację bazy danych Oracle z AWS EC2 do AWS RDS