😃

変換関数および条件式(DECODE,NVL,NVL2)

に公開

はじめに

Oracle SQL では、条件分岐やNULL値の扱いを柔軟に行うために、
DECODE・NVL・NVL2 といった「値の変換系関数」が用意されています。
これらの関数を使いこなすことで、CASE式を使わずに条件ごとの表示制御や
NULLデータの補完処理を簡潔に記述することができます。

DECODE関数

DECODE関数は、第1引数に指定された式の値と、第2引数以降に指定された条件を順に判定し、値が合致した条件に対応する戻り値を返します。

SELECT employee_name,
       DECODE(department_id,
              10, '営業部',
              20, '人事部',
              30, '開発部',
              'その他') AS department_name
FROM employees;


| department_id | 結果  |
| ------------- | --- |
| 10            | 営業部 |
| 20            | 人事部 |
| 40            | その他 |

注意点

DECODE関数に比較演算子を使用することはできない。

SELECT employee_id, employee_name, DECODE(salary, salary > 400000, 'High', salary < 200000, 'low', 'middle') sal FROM employees;

DECODEの戻り値型は第3引数で決まる ─ 暗黙的変換の実証

-- 🧱 テーブル内容
SELECT * FROM employees;

EMPLOYEE_ID | EMPLOYEE_NAME | SALARY
-------------+----------------+---------
1            | JOY            | 500000
2            | MIKE           | 300000
3            | LUCAS          | (NULL)

暗黙的変換できる場合はエラーにはなりません。

-- ✅ パターン①:暗黙的変換あり
SELECT employee_id, employee_name,
       DECODE(NULLIF(salary, 500000), NULL, '-', salary) AS sal
FROM employees;

EMPLOYEE_ID | EMPLOYEE_NAME | SAL
-------------+----------------+--------
1            | JOY            | -
2            | MIKE           | 300000
3            | LUCAS          | -
-- ✅ パターン②:明示的変換(TO_CHAR)
SELECT employee_id, employee_name,
       DECODE(NULLIF(salary, 500000), NULL, '-', TO_CHAR(salary)) AS sal
FROM employees;

EMPLOYEE_ID | EMPLOYEE_NAME | SAL
-------------+----------------+--------
1            | JOY            | -
2            | MIKE           | 300000
3            | LUCAS          | -

第3引数とそれ以降の方が不一致の場合にエラーになります。

--  パターン③:型不一致でエラー発生
SELECT employee_id, employee_name,
       DECODE(NULLIF(salary, 500000), NULL, salary, '-') AS sal
FROM employees;

ORA-01722: invalid number

NVLとNVL2の違い

SQL> select * from emp_test;

EMP_NAME                   COMM
-------------------- ----------
JOHN                       1000
MIKE
SARA                        500
JOY

NVL

NVL関数とは、NULL値を他の値に置き換えることができる関数です。
NULLでなかった場合は第一引数を返却します

comm(歩合)が NULL の場合 → 0 を返す

comm が NULL でない場合 → そのまま comm を返す

SELECT 
  emp_name,
  comm,
  NVL(comm, 0) AS nvl_result
FROM emp_test;

EMP_NAME                   COMM NVL_RESULT
-------------------- ---------- ----------
JOHN                       1000       1000
MIKE                                     0
SARA                        500        500
JOY                                      0

NVL関数の第2引数には、第1引数と同じデータ型の値を指定しなければなりません。

SQL> select * from emp_test2;

EMP_NAME                 SALARY HIREDATE
-------------------- ---------- ---------
JOHN                       5000 10-APR-20
MIKE                            05-NOV-22

SQL> DESC emp_test2;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 EMP_NAME                                           VARCHAR2(20)
 SALARY                                             NUMBER
 HIREDATE                                           DATE

-- ▼ 1. 正常パターン(数値同士 OK)
 SELECT  emp_name,
  NVL(salary, 0) AS nvl_ok FROM emp_test2;

  EMP_NAME                 NVL_OK
-------------------- ----------
JOHN                       5000
MIKE                          0

-- ▼ 2. 暗黙的変換あり(数値 → 文字列 OK)
SELECT 
  emp_name,
  NVL(TO_CHAR(salary), 'NO DATA') AS nvl_char
FROM emp_test2;

EMP_NAME             NVL_CHAR
-------------------- ----------------------------------------
JOHN                 5000
MIKE                 NO DATA

SELECT 
  emp_name,
  NVL(salary, hiredate) AS nvl_error
FROM emp_test2;

-- ▼ 3. 型不一致エラー(数値 と 日付 ❌)
ERROR at line 3:
ORA-00932: inconsistent datatypes: expected NUMBER got DATE

NVL2

NVL2を使用すると、指定された式がNULLかどうかに基づく問合せによって戻される値を判断できます。

SELECT 
  emp_name,
  comm,
  NVL2(comm, 'YES', 'NO') AS nvl2_result
FROM emp_test;

EMP_NAME                   COMM NVL
-------------------- ---------- ---
JOHN                       1000 YES
MIKE                            NO
SARA                        500 YES
JOY                             NO
関数名 構文 意味 NULLのとき NULLでないとき
NVL NVL(expr1, expr2) expr1 が NULL の場合、expr2 を返す expr2 expr1
NVL2 NVL2(expr1, expr2, expr3) expr1 が NULL でない場合は expr2、NULL の場合は expr3 を返す expr3 expr2

Discussion