Kort antwoord, nee.
Het iets langere antwoord is bijna.
Het verschijnt alleen dat het resultaat van elke uitspraak identiek is. Als we de DUMP-functie gebruiken om de geretourneerde gegevenstypen te evalueren, ziet u wat ik bedoel:
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
U kunt zien dat het gegevenstype van DECODE 1 is, terwijl de twee CASE-statements een datatype van 2 "retourneren". Met behulp van Oracle's Data Type Summary, retourneert DECODE een VARCHAR2 (datatype 1) terwijl de CASE-statements "retourneren" " nummers (gegevenstype 2).
Ik neem aan dat dit gebeurt omdat, zoals de namen suggereren, DECODE een functie is en CASE niet, wat impliceert dat ze intern anders zijn geïmplementeerd. Er is geen echte manier om dit te bewijzen.
Je zou kunnen denken dat dit helemaal niets uitmaakt. Als het een getal moet zijn, zal Oracle het teken impliciet naar een getal converteren volgens de impliciete conversieregels, toch? Dit is ook niet waar, het zal niet werken in een UNION aangezien de datatypes hebben identiek zijn; Oracle zal geen impliciete conversie uitvoeren om het u gemakkelijk te maken. Ten tweede, dit is wat Oracle zegt over impliciete conversie:
Oracle raadt u om de volgende redenen aan om expliciete conversies op te geven in plaats van te vertrouwen op impliciete of automatische conversies:
SQL-instructies zijn gemakkelijker te begrijpen als u expliciete conversiefuncties voor gegevenstypen gebruikt.
Impliciete conversie van gegevenstypes kan een negatieve invloed hebben op de prestaties, vooral als het gegevenstype van een kolomwaarde wordt geconverteerd naar een constante in plaats van andersom.
Impliciete conversie hangt af van de context waarin deze plaatsvindt en werkt mogelijk niet in alle gevallen op dezelfde manier. Een impliciete conversie van een datetime-waarde naar een VARCHAR2-waarde kan bijvoorbeeld een onverwacht jaar opleveren, afhankelijk van de waarde van de parameter NLS_DATE_FORMAT.
Algoritmen voor impliciete conversie kunnen worden gewijzigd tussen softwarereleases en tussen Oracle-producten. Het gedrag van expliciete conversies is voorspelbaarder.
Dat is geen mooie lijst; maar het voorlaatste punt brengt me mooi op daten. Als we de vorige zoekopdracht nemen en deze omzetten in een zoekopdracht die in plaats daarvan een datum gebruikt:
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;
Nogmaals, met DUMP voor deze query retourneren de CASE-instructies gegevenstype 12, een DATE. De DECODE heeft sysdate
geconverteerd in een 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
Merk op (in de SQL Fiddle) dat de DATE is omgezet in een teken met behulp van de sessies NLS_DATE_FORMAT.
Het hebben van een datum die impliciet is omgezet in een VARCHAR2 kan problemen veroorzaken. Als je van plan bent TO_CHAR te gebruiken om je datum in een teken om te zetten, zal je zoekopdracht breken waar je hem niet verwacht.
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
Evenzo werkt datumberekening niet meer:
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 is dat DECODE de uitdrukking alleen naar een VARCHAR2 converteert als een van de mogelijke resultaten NULL is. Als de standaardwaarde NULL is, gebeurt dit niet. Bijvoorbeeld:
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
Merk op dat de DECODE een gegevenstype van 13 heeft geretourneerd. Dit is niet gedocumenteerd, maar is, neem ik aan, een type datum, aangezien rekenkunde voor datums enz. werkt.
Kortom, vermijd DECODE indien mogelijk; u krijgt mogelijk niet noodzakelijk de gegevenstypen die u verwacht. Om Tom Kyte te citeren:
Decoderen is enigszins obscuur -- CASE is heel erg duidelijk. Dingen die gemakkelijk te doen zijn bij het decoderen, zijn gemakkelijk te doen in CASE, dingen die moeilijk of bijna onmogelijk zijn om te doen bij het decoderen, zijn gemakkelijk te doen in CASE. CASE wint logischerwijs zonder meer.
Om compleet te zijn zijn er twee functionele verschillen tussen DECODE en CASE.
- DECODE kan niet worden gebruikt binnen PL/SQL.
-
CASE kan niet worden gebruikt om nulls rechtstreeks te vergelijken
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