Kort svar, nej.
Det lidt længere svar er næsten.
Det vises kun at resultatet opnået fra hver udsagn er identisk. Hvis vi bruger DUMP-funktionen til at evaluere de returnerede datatyper, vil du se, hvad jeg mener:
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
SQL Fiddle
Du kan se, at datatypen for DECODE er 1, hvorimod de to CASE-sætninger "returnerer" en datatype på 2. Ved at bruge Oracles Data Type Summary returnerer DECODE en VARCHAR2 (datatype 1), mens CASE-sætningerne "returnerer" " numre (datatype 2).
Jeg antager, at dette sker, fordi, som navnene antyder, DECODE er en funktion og CASE er det ikke, hvilket betyder, at de er blevet implementeret anderledes internt. Der er ingen reel måde at bevise dette på.
Du tror måske, at dette ikke rigtig påvirker noget. Hvis du har brug for, at det er et tal, vil Oracle implicit konvertere tegnet til et tal under de implicitte konverteringsregler, ikke? Dette er heller ikke sandt, det vil ikke fungere i en UNION, som datatyperne har at være identisk; Oracle vil ikke foretage nogen implicit konvertering for at gøre tingene nemme for dig. For det andet, her er hvad Oracle siger om implicit konvertering:
Oracle anbefaler, at du angiver eksplicitte konverteringer i stedet for at stole på implicitte eller automatiske konverteringer af disse grunde:
-
SQL-sætninger er nemmere at forstå, når du bruger eksplicitte datatypekonverteringsfunktioner.
-
Implicit datatypekonvertering kan have en negativ indvirkning på ydeevnen, især hvis datatypen for en kolonneværdi konverteres til en konstant i stedet for omvendt.
-
Implicit konvertering afhænger af den kontekst, den finder sted i, og fungerer muligvis ikke på samme måde i alle tilfælde. For eksempel kan implicit konvertering fra en datetime-værdi til en VARCHAR2-værdi returnere et uventet år afhængigt af værdien af NLS_DATE_FORMATparameteren.
-
Algoritmer til implicit konvertering kan ændres på tværs af softwareudgivelser og blandt Oracle-produkter. Eksplicitte konverteringers adfærd er mere forudsigelig.
Det er ikke en køn liste; men det næstsidste point bringer mig fint på dates. Hvis vi tager den forrige forespørgsel og konverterer den til en, der bruger en dato i stedet:
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;
Endnu en gang, ved at bruge DUMP på denne forespørgsel, returnerer CASE-sætningerne datatype 12, en DATE. DECODE har konverteret sysdate
ind i en 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
SQL Fiddle
Bemærk (i SQL Fiddle), at DATE er blevet konverteret til et tegn ved hjælp af sessionerne NLS_DATE_FORMAT.
At have en dato, der implicit er blevet konverteret til en VARCHAR2, kan forårsage problemer. Hvis du har til hensigt at bruge TO_CHAR til at konvertere din dato til et tegn, vil din forespørgsel bryde, hvor du ikke forventer det.
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
SQL Fiddle
Ligeledes virker dato-aritmetik ikke længere:
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
SQL Fiddle
Interessant nok konverterer DECODE kun udtrykket til en VARCHAR2, hvis et af de mulige resultater er NULL. Hvis standardværdien er NULL, sker dette ikke. For eksempel:
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
SQL Fiddle
Bemærk, at DECODE har returneret en datatype på 13. Dette er ikke dokumenteret, men jeg antager, at det er en type dato, da datoregning osv. virker.
Kort sagt, undgå DECODE, hvis du overhovedet kan; du får muligvis ikke nødvendigvis de datatyper, du forventer. For at citere Tom Kyte:
Afkodning er noget obskur -- CASE er meget meget tydeligt. Ting, der er lette at gøre i afkodning, er nemme at gøre i CASE, ting, der er svære eller næsten umulige at gøre med afkodning, er nemme at gøre i CASE. CASE, logisk set, vinder hænder ned.
Bare for at være komplet er der to funktionelle forskelle mellem DECODE og CASE.
- DECODE kan ikke bruges i PL/SQL.
-
CASE kan ikke bruges til at sammenligne nuller direkte
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
SQL Fiddle