短い答え、いいえ。
少し長い答えはほぼです。
表示される 各ステートメントから得られた結果は同一であること。 DUMP関数を使用して、返されたデータ型を評価すると、私が何を意味するかがわかります。
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フィドル
DECODEのデータ型が1であるのに対し、2つのCASEステートメントは2のデータ型を「返す」ことがわかります。Oracleのデータ型の概要を使用すると、DECODEはVARCHAR2(データ型1)を返しますが、CASEステートメントは「 "番号(データ型2)。
名前が示すように、DECODEは関数であるため、これが発生すると思います。 CASEはそうではありません。これは、内部で異なる方法で実装されていることを意味します。これを証明する実際の方法はありません。
これは実際には何の影響もないと思うかもしれません。数値にする必要がある場合、Oracleは暗黙の変換規則に基づいて文字を数値に暗黙的に変換します。これも当てはまりません。データ型があるため、UNIONでは機能しません。 同一であること。オラクルは、物事を簡単にするために暗黙の変換を行いません。次に、オラクルが暗黙の変換について言っていることは次のとおりです。
次の理由から、暗黙的または自動変換に依存するのではなく、明示的な変換を指定することをお勧めします。
明示的なデータ型変換関数を使用すると、SQLステートメントが理解しやすくなります。
暗黙的なデータ型変換は、特に列値のデータ型がその逆ではなく定数のデータ型に変換される場合、パフォーマンスに悪影響を与える可能性があります。
暗黙的な変換は、それが発生するコンテキストによって異なり、すべての場合で同じように機能するとは限りません。たとえば、日時値からVARCHAR2値への暗黙の変換は、NLS_DATE_FORMATパラメータの値によっては予期しない年を返す場合があります。
暗黙的な変換のアルゴリズムは、ソフトウェアリリース間およびOracle製品間で変更される可能性があります。明示的なコンバージョンの動作はより予測可能です。
それはきれいなリストではありません。しかし、最後から2番目のポイントは私を日付にうまく連れて行ってくれます。前のクエリを取得して、代わりに日付を使用するクエリに変換する場合:
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;
この場合も、このクエリでDUMPを使用すると、CASEステートメントはデータ型12、DATEを返します。 DECODEはsysdate
を変換しました 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フィドル
(SQLフィドルで)DATEはセッションNLS_DATE_FORMATを使用して文字に変換されていることに注意してください。
暗黙的にVARCHAR2に変換された日付があると、問題が発生する可能性があります。 TO_CHARを使用して日付を文字に変換する場合、予期しない場所でクエリが中断されます。
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フィドル
同様に、日付演算は機能しなくなりました:
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フィドル
興味深いことに、DECODEは、考えられる結果の1つがNULLの場合にのみ、式をVARCHAR2に変換します。デフォルト値がNULLの場合、これは発生しません。例:
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フィドル
DECODEが13のデータ型を返したことに注意してください。これは文書化されていませんが、日付演算などの日付の種類が機能すると思います。
つまり、可能であればDECODEは避けてください。期待するデータ型を必ずしも取得できない場合があります。トム・カイトを引用するには:
デコードはややあいまいです-CASEは非常に明確です。デコードで簡単にできることはCASEで簡単に実行でき、デコードで実行するのが難しいかほぼ不可能なことはCASEで簡単に実行できます。論理的には、CASEが勝ちます。
完全を期すために、2つの機能があります DECODEとCASEの違い。
- DECODEはPL/SQL内では使用できません。
-
CASEを使用して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
SQLフィドル