😃
変換関数および条件式(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