Kurze Antwort, nein.
Die etwas längere Antwort ist fast.
Es erscheint nur dass das Ergebnis jeder Anweisung identisch ist. Wenn wir die DUMP-Funktion verwenden, um die zurückgegebenen Datentypen auszuwerten, werden Sie sehen, was ich meine:
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
Sie können sehen, dass der Datentyp von DECODE 1 ist, während die beiden CASE-Anweisungen einen Datentyp von 2 "zurückgeben". Unter Verwendung von Oracles Data Type Summary gibt DECODE ein VARCHAR2 (Datentyp 1) zurück, während die CASE-Anweisungen "zurückgeben". " Zahlen (Datentyp 2).
Ich nehme an, dass dies geschieht, weil DECODE, wie der Name schon sagt, eine Funktion ist und CASE ist es nicht, was impliziert, dass sie intern anders implementiert wurden. Es gibt keine wirkliche Möglichkeit, dies zu beweisen.
Sie könnten denken, dass dies nicht wirklich etwas beeinflusst. Wenn Sie eine Zahl benötigen, konvertiert Oracle das Zeichen implizit in eine Zahl gemäß den impliziten Konvertierungsregeln, richtig? Das stimmt auch nicht, es funktioniert nicht in einer UNION wie die Datentypen haben identisch sein; Oracle führt keine implizite Konvertierung durch, um Ihnen die Arbeit zu erleichtern. Zweitens sagt Oracle Folgendes über die implizite Konvertierung:
Oracle empfiehlt aus folgenden Gründen, dass Sie explizite Konvertierungen angeben, anstatt sich auf implizite oder automatische Konvertierungen zu verlassen:
-
SQL-Anweisungen sind leichter verständlich, wenn Sie explizite Datentyp-Konvertierungsfunktionen verwenden.
-
Die implizite Datentypkonvertierung kann sich negativ auf die Leistung auswirken, insbesondere wenn der Datentyp eines Spaltenwerts in den einer Konstanten konvertiert wird und nicht umgekehrt.
-
Die implizite Konvertierung hängt vom Kontext ab, in dem sie auftritt, und funktioniert möglicherweise nicht in jedem Fall auf die gleiche Weise. Beispielsweise kann die implizite Konvertierung von einem datetime-Wert in einen VARCHAR2-Wert abhängig vom Wert des Parameters NLS_DATE_FORMAT ein unerwartetes Jahr zurückgeben.
-
Algorithmen für die implizite Konvertierung können sich über Softwareversionen und zwischen Oracle-Produkten hinweg ändern. Das Verhalten expliziter Conversions ist vorhersehbarer.
Das ist keine schöne Liste; aber der vorletzte punkt bringt mich schön auf daten. Wenn wir die vorherige Abfrage nehmen und sie in eine umwandeln, die stattdessen ein Datum verwendet:
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;
Auch hier geben die CASE-Anweisungen bei Verwendung von DUMP bei dieser Abfrage den Datentyp 12, ein DATUM, zurück. Der DECODE hat sysdate
konvertiert in ein 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
Beachten Sie (in der SQL-Fiddle), dass das DATE mithilfe der Sitzungen NLS_DATE_FORMAT.
in ein Zeichen umgewandelt wurdeEin Datum, das implizit in ein VARCHAR2 konvertiert wurde, kann Probleme verursachen. Wenn Sie beabsichtigen, TO_CHAR zu verwenden, um Ihr Datum in ein Zeichen umzuwandeln, bricht Ihre Abfrage dort ab, wo Sie es nicht erwarten.
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
Ebenso funktioniert die Datumsarithmetik nicht mehr:
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
Interessanterweise konvertiert DECODE den Ausdruck nur dann in ein VARCHAR2, wenn eines der möglichen Ergebnisse NULL ist. Wenn der Standardwert NULL ist, passiert dies nicht. Zum Beispiel:
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
Beachten Sie, dass DECODE einen Datentyp von 13 zurückgegeben hat. Dies ist nicht dokumentiert, aber ich nehme an, dass es sich um einen Datumstyp handelt, da Datumsarithmetik usw. funktioniert.
Kurz gesagt, vermeiden Sie DECODE, wenn Sie können; Möglicherweise erhalten Sie nicht unbedingt die erwarteten Datentypen. Um Tom Kyte zu zitieren:
Die Dekodierung ist etwas unklar – CASE ist sehr, sehr klar. Dinge, die beim Decodieren einfach zu tun sind, sind in CASE einfach zu tun, Dinge, die beim Decodieren schwer oder fast unmöglich zu tun sind, sind in CASE einfach zu tun. CASE gewinnt logischerweise zweifellos.
Der Vollständigkeit halber gibt es zwei funktionale Unterschiede zwischen DECODE und CASE.
- DECODE kann nicht innerhalb von PL/SQL verwendet werden.
-
CASE kann nicht verwendet werden, um Nullen direkt zu vergleichen
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