【Oracle】CASE 式と DECODE 関数の違いと使い分け|構文・NULL・型変換・パフォーマンス・PL/SQL・実務パターンまで解説

【Oracle】CASE 式と DECODE 関数の違いと使い分け|構文・NULL・型変換・パフォーマンス・PL/SQL・実務パターンまで解説 Oracle

Oracle で条件分岐を行うには CASE 式と DECODE 関数の 2 つの方法があります。どちらも「条件に応じて異なる値を返す」機能ですが、NULL の扱い・型変換の動作・SQL 標準への準拠・PL/SQL での使い方が異なります。

本記事では、CASE 式の 2 つの構文(単純 CASE / 検索 CASE)と DECODE を比較しながら、NULL の等値判定の違い暗黙型変換の罠パフォーマンスの差異PL/SQL での CASE 文、そしてORDER BY・GROUP BY・UPDATE 内での CASE 活用まで解説します。

この記事でわかること
・単純 CASE 式と検索 CASE 式の構文と使い分け
・DECODE 関数の構文(概要)
・CASE vs DECODE の完全比較表
・NULL の扱いの違い(DECODE: NULL=NULL、CASE: IS NULL が必要)
・戻り値の型変換の違い(DECODE: 暗黙変換、CASE: 明示的)
・パフォーマンスの違い
・PL/SQL での CASE 式と CASE 文
・ORDER BY / GROUP BY / UPDATE / INSERT での CASE 活用パターン
スポンサーリンク

CASE 式の構文

単純 CASE 式(等値比較)

SQL(単純 CASE)
-- 構文: CASE 式 WHEN 値 THEN 結果 ... ELSE デフォルト END
SELECT employee_id,
       department_id,
       CASE department_id
           WHEN 10 THEN '経理部'
           WHEN 20 THEN '研究開発部'
           WHEN 30 THEN '営業部'
           ELSE 'その他'
       END AS dept_name
FROM employees;

検索 CASE 式(任意の条件)

SQL(検索 CASE)
-- 構文: CASE WHEN 条件 THEN 結果 ... ELSE デフォルト END
SELECT employee_id,
       salary,
       CASE
           WHEN salary >= 10000 THEN 'A(高給)'
           WHEN salary >= 5000  THEN 'B(中間)'
           WHEN salary >= 3000  THEN 'C(標準)'
           ELSE 'D(見直し対象)'
       END AS salary_grade
FROM employees;
種類 比較方式 適するケース
単純 CASE 等値(=)のみ 1 つの列の値でマッピング(コード→名称変換など)
検索 CASE 任意の条件式(>=, BETWEEN, LIKE, IS NULL 等) 範囲判定・複合条件・NULL 判定が必要な場合
迷ったら検索 CASE を使う
単純 CASE は等値比較しかできず、後から「範囲判定も追加したい」となると書き換えが必要です。検索 CASE なら等値比較も範囲判定もすべて対応できるため、汎用性が高いです。

DECODE 関数の構文(概要)

SQL(DECODE)
-- 構文: DECODE(式, 比較値1, 結果1, 比較値2, 結果2, ..., デフォルト)
SELECT employee_id,
       department_id,
       DECODE(department_id,
              10, '経理部',
              20, '研究開発部',
              30, '営業部',
              'その他'
       ) AS dept_name
FROM employees;

DECODE は等値比較のみに対応する Oracle 独自の関数です。上記の例は単純 CASE とまったく同じ結果を返します。DECODE の詳しい使い方は「DECODE 関数の使い方完全解説」を参照してください。

CASE vs DECODE 完全比較表

項目 CASE 式 DECODE 関数
SQL 標準 SQL 標準(全 RDBMS 対応) Oracle 独自
比較方式 等値(単純CASE)+ 任意条件(検索CASE) 等値のみ
NULL の比較 IS NULL が必要
(WHEN NULL は動作しない)
NULL = NULL として扱う
(特別な記述不要)
戻り値の型 最も広い型に統一(明示的なルール) 第 1 結果の型に暗黙変換
ネスト 自然に読める 可読性が大幅に低下
可読性 高い(条件が明示的) 低い(引数の羅列)
PL/SQL CASE 式 + CASE 文の両方使える SQL 内でのみ(PL/SQL 文としては不可)
パフォーマンス 同等 同等(オプティマイザが内部変換)
使える場所 SELECT / WHERE / ORDER BY / GROUP BY / UPDATE / INSERT / PL/SQL SELECT / WHERE / ORDER BY / GROUP BY / UPDATE / INSERT

NULL の扱いの違い

CASE と DECODE で最も注意すべき違いが NULL の比較動作です。

SQL(NULL 比較の違い)
-- DECODE: NULL = NULL として扱う(特別な記述不要)
SELECT DECODE(NULL, NULL, 'MATCH', 'NO MATCH') FROM DUAL;
-- 結果: MATCH(NULL 同士を等しいと判定)

-- 単純 CASE: WHEN NULL は動作しない
SELECT CASE NULL WHEN NULL THEN 'MATCH' ELSE 'NO MATCH' END FROM DUAL;
-- 結果: NO MATCH(NULL = NULL は UNKNOWN → ELSE に流れる)

-- 検索 CASE: IS NULL を使えば判定できる
SELECT CASE WHEN NULL IS NULL THEN 'MATCH' ELSE 'NO MATCH' END FROM DUAL;
-- 結果: MATCH
SQL(実務での NULL 判定パターン)
-- 列に NULL がある場合のマッピング

-- DECODE: commission_pct が NULL なら '固定給'
SELECT DECODE(commission_pct, NULL, '固定給', '歩合あり') FROM employees;

-- CASE: IS NULL を使う
SELECT CASE WHEN commission_pct IS NULL THEN '固定給'
            ELSE '歩合あり'
       END FROM employees;

-- 単純 CASE では NULL 判定できない(検索 CASE を使う)
NULL 判定の使い分け
・NULL を頻繁に比較する場面 → DECODE がシンプル(NULL = NULL が自動判定)
・それ以外の場面 → CASE WHEN col IS NULL が明確で安全
ただし NVL / NVL2 で NULL を事前に変換する方がさらにシンプルなことが多いです。

戻り値の型変換の違い

SQL(型変換の違い)
-- DECODE: 第 1 結果の型に合わせて暗黙変換
SELECT DECODE(1, 1, 'TEXT', 2, 100) FROM DUAL;
-- 第 1 結果 'TEXT' が VARCHAR2 → 100 も VARCHAR2 に暗黙変換 → '100'

-- CASE: 全分岐の型から最も広い型を自動推定
SELECT CASE 1 WHEN 1 THEN 'TEXT' WHEN 2 THEN 100 END FROM DUAL;
-- ORA-00932: inconsistent datatypes(VARCHAR2 と NUMBER は混在不可)
DECODE の暗黙型変換は予期しないバグの原因
DECODE は第 1 結果の型に後続の結果を暗黙変換するため、意図しない型変換(例: 数値が文字列になる)が発生します。CASE 式は型の不一致をエラーにしてくれるため、バグを早期発見できます。安全性の面では CASE 式が優位です。

DECODE から CASE への書き換え

DECODE CASE 書き換え
DECODE(col, ‘A’, 1, ‘B’, 2, 0) CASE col WHEN ‘A’ THEN 1 WHEN ‘B’ THEN 2 ELSE 0 END
DECODE(col, NULL, ‘NULL!’, col) CASE WHEN col IS NULL THEN ‘NULL!’ ELSE col END
DECODE(SIGN(a-b), 1, ‘a>b’, -1, ‘a<b’, ‘a=b’) CASE WHEN a > b THEN ‘a>b’ WHEN a < b THEN ‘a<b’ ELSE ‘a=b’ END
DECODE(status, 1, DECODE(type, A, X, Y), Z) CASE WHEN status=1 AND type=’A’ THEN X WHEN status=1 THEN Y ELSE Z END
ネストした DECODE は CASE に書き換えるべき
DECODE のネスト(DECODE の中に DECODE)は可読性が著しく低下します。検索 CASE に書き換えれば、条件が一目瞭然になります。新規開発では CASE を使い、既存コードの DECODE は機会があれば CASE に移行することを推奨します。

PL/SQL での CASE

PL/SQL では CASE を(値を返す)と(処理を実行する)の2 通りで使えます。DECODE は SQL 文の中でしか使えません。

SQL(PL/SQL CASE 式: 値を返す)
DECLARE
    v_dept_id NUMBER := 10;
    v_name   VARCHAR2(50);
BEGIN
    -- CASE 式: 変数に代入
    v_name := CASE v_dept_id
                  WHEN 10 THEN '経理部'
                  WHEN 20 THEN '研究開発部'
                  ELSE 'その他'
              END;
    DBMS_OUTPUT.PUT_LINE(v_name);
END;
/
SQL(PL/SQL CASE 文: 処理を分岐)
DECLARE
    v_grade CHAR(1) := 'A';
BEGIN
    -- CASE 文: 分岐ごとに処理を実行
    CASE v_grade
        WHEN 'A' THEN
            DBMS_OUTPUT.PUT_LINE('Excellent');
        WHEN 'B' THEN
            DBMS_OUTPUT.PUT_LINE('Good');
        WHEN 'C' THEN
            DBMS_OUTPUT.PUT_LINE('Average');
        ELSE
            DBMS_OUTPUT.PUT_LINE('Below Average');
    END CASE;    -- END CASE(セミコロンあり)
END;
/
種類 末尾の書き方 用途
CASE 式(SQL / PL/SQL 両方) END(セミコロンなし) 値を返す(SELECT / 代入 / 引数に使用)
CASE 文(PL/SQL のみ) END CASE;(セミコロンあり) 処理を分岐実行(IF-ELSIF の代替)

実務パターン集

パターン(1): ORDER BY での並び替え制御

SQL(CASE で並び替え順序をカスタマイズ)
-- ステータス: ACTIVE → PENDING → INACTIVE の順に表示
SELECT employee_id, last_name, status
FROM employees
ORDER BY
    CASE status
        WHEN 'ACTIVE'   THEN 1
        WHEN 'PENDING'  THEN 2
        WHEN 'INACTIVE' THEN 3
        ELSE 4
    END;

パターン(2): GROUP BY + CASE で条件付き集計

SQL(CASE でグルーピング条件を動的に作成)
-- 給与を 3 段階に分けて人数を集計
SELECT
    CASE
        WHEN salary >= 10000 THEN '高給(10000以上)'
        WHEN salary >= 5000  THEN '中間(5000-9999)'
        ELSE '標準(5000未満)'
    END AS salary_band,
    COUNT(*) AS emp_count,
    AVG(salary) AS avg_salary
FROM employees
GROUP BY
    CASE
        WHEN salary >= 10000 THEN '高給(10000以上)'
        WHEN salary >= 5000  THEN '中間(5000-9999)'
        ELSE '標準(5000未満)'
    END
ORDER BY avg_salary DESC;

パターン(3): UPDATE SET に CASE を使う

SQL(条件付き UPDATE)
-- 部門ごとに異なる昇給率を適用
UPDATE employees
SET salary = salary * CASE department_id
                          WHEN 10 THEN 1.10  -- 経理: 10%
                          WHEN 20 THEN 1.15  -- 研究開発: 15%
                          WHEN 30 THEN 1.05  -- 営業: 5%
                          ELSE 1.08           -- その他: 8%
                      END
WHERE status = 'ACTIVE';

パターン(4): SELECT で横展開(ピボット的な使い方)

SQL(CASE でピボット集計)
-- 月別の注文件数を横展開(PIVOT の代替)
SELECT
    product_name,
    SUM(CASE WHEN TO_CHAR(order_date, 'MM') = '01' THEN 1 ELSE 0 END) AS jan,
    SUM(CASE WHEN TO_CHAR(order_date, 'MM') = '02' THEN 1 ELSE 0 END) AS feb,
    SUM(CASE WHEN TO_CHAR(order_date, 'MM') = '03' THEN 1 ELSE 0 END) AS mar
FROM orders
WHERE order_date >= DATE '2026-01-01'
GROUP BY product_name;

パターン(5): WHERE 句での CASE

SQL(条件を動的に切り替え)
-- パラメータに応じて検索条件を切り替え
SELECT * FROM employees
WHERE department_id = CASE :search_mode
                          WHEN 'ALL' THEN department_id  -- 全部門
                          ELSE :target_dept_id            -- 指定部門
                      END;

使い分けの判断基準

場面 推奨 理由
新規開発 CASE SQL 標準。可読性が高い。型安全
範囲判定(>=, BETWEEN 等) 検索 CASE DECODE は等値比較しかできない
NULL の等値比較が多い DECODE がシンプル DECODE は NULL = NULL を自動判定
他 RDBMS への移植が必要 CASE DECODE は Oracle 独自
PL/SQL 内の分岐処理 CASE 文 DECODE は PL/SQL 文として使えない
既存コードが DECODE そのまま維持 / 余裕があれば CASE に移行 動作に問題がなければ無理に変えない
結論: 迷ったら CASE を使う
CASE は SQL 標準で全 RDBMS 対応、等値も範囲も対応、型安全、PL/SQL でも使える――とあらゆる面で DECODE を上回ります。DECODE を積極的に選ぶ理由は「NULL の等値比較が多い場面」と「既存コードの保守」くらいです。新規開発では CASE を標準として使ってください。

よくある質問

QCASE と DECODE でパフォーマンスに差はありますか?
Aほとんど差はありません。Oracle のオプティマイザは DECODE を内部的に CASE と同等の実行計画に変換します。パフォーマンスではなく、可読性・安全性・移植性で選んでください。
Q単純 CASE で NULL を判定できますか?
Aできません。CASE col WHEN NULL THEN ... は動作しません。内部的に col = NULL として評価され、常に UNKNOWN になるためです。NULL 判定は検索 CASECASE WHEN col IS NULL THEN ...)を使ってください。
QELSE を省略するとどうなりますか?
ACASE 式で ELSE を省略し、どの WHEN にも該当しなかった場合、NULL が返ります。DECODE も同様で、デフォルト値を省略すると NULL になります。意図しない NULL を防ぐため、ELSE は常に明示的に記述することを推奨します。
QCASE の WHEN は上から順に評価されますか?
Aはい。WHEN は上から順に評価され、最初に TRUE になった THEN の値が返されます。複数の WHEN に該当する場合でも、2 番目以降は評価されません(短絡評価)。そのため「より狭い条件を先に書く」のが基本です。
QCASE 式と CASE 文の違いは何ですか?
ACASE 式は値を返し、SELECT / 代入 / 引数の中で使います。末尾は END
CASE 文は PL/SQL 専用で、処理を分岐実行します。末尾は END CASE;
CASE 式は SQL でも PL/SQL でも使えますが、CASE 文は PL/SQL のみです。
Q既存コードの DECODE を CASE に書き換えるべきですか?
A動作に問題がなければ無理に書き換える必要はありません。ただし、ネストした DECODE(DECODE の中に DECODE)や条件が 5 個以上ある DECODE は可読性が著しく低いため、リファクタリングの機会に CASE に移行することを推奨します。新規コードでは CASE を標準にしてください。

まとめ

CASE 式と DECODE 関数の使い分けの要点をまとめます。

やりたいこと 推奨方法
等値比較で値をマッピング CASE col WHEN ‘A’ THEN 1 … END(または DECODE)
範囲判定(>= / BETWEEN / LIKE) CASE WHEN salary >= 5000 THEN … END
NULL の列を別の値に変換 CASE WHEN col IS NULL THEN … END(または DECODE(col, NULL, …))
ORDER BY の並び順をカスタマイズ ORDER BY CASE status WHEN … END
GROUP BY で条件付き集計 SUM(CASE WHEN cond THEN 1 ELSE 0 END)
UPDATE で条件付き更新 SET col = CASE WHEN … END
PL/SQL で分岐処理 CASE … WHEN … THEN … END CASE;
他 RDBMS への移植が必要 CASE(SQL 標準)

DECODE 関数の詳しい使い方は「DECODE 関数の使い方完全解説」も併せて参照してください。

CASE式の条件集計(SUM/COUNT CASE WHEN)・ORDER BY動的ソート・PIVOT代替・Oracle 23aiでのGROUP BYエイリアス改善など、SQL全般での活用パターンはCASE式完全ガイドも参照してください。