sql >> データベース >  >> RDS >> Oracle

CASEステートメントとDECODEは同等ですか?

    短い答え、いいえ。

    少し長い答えはほぼです。

    表示される 各ステートメントから得られた結果は同一であること。 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の違い。

    1. DECODEはPL/SQL内では使用できません。
    2. 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フィドル



    1. SQLServer本番DBAに関する5つの便利なヒント

    2. AzureSQLデータベースでの自動インデックス管理

    3. PostgreSQL 13:スロットにプライマリを殺させないでください

    4. 文字列内の最初の非数値文字を検索するSQL