短い答え、いいえ。
少し長い答えはほぼです。
各ステートメントから得られる結果が同一であるように見えるだけです。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 のData Type Summaryを使用すると、DECODE は VARCHAR2 (データ型 1) を返しますが、CASE ステートメントは「 " 数字 (データ型 2)。
名前が示すように、DECODE は関数であり、CASE は関数ではないため、これが発生すると思います。これは、内部で異なる方法で実装されていることを意味します。これを証明する実際の方法はありません。
これは実際には何の影響もないと考えるかもしれません。数値にする必要がある場合、Oracle は暗黙的な変換規則に従って暗黙的に文字を数値に変換します。これも正しくありません。データ型が同一でなければならないため、UNION では機能しません。オラクルは、物事を簡単にするために暗黙的な変換を行いません。第二に、暗黙的な変換についてOracleが言っていることは次のとおりです。
次の理由から、暗黙的または自動変換に依存するのではなく、明示的な変換を指定することをお薦めします:
明示的なデータ型変換関数を使用すると、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 フィドル
セッションNLS_DATE_FORMATを使用して DATE が文字に変換されていることに注意してください(SQL Fiddle内) 。
暗黙的に 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 で実行しやすいです。ケース、論理的には、勝者です。
完全にするために、DECODE と CASE には 2 つの機能上の違いがあります。
- 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 フィドル