
OracleデータベースでNULLをどう扱うかは、業務アプリの正確性・可読性・パフォーマンスに直結します。本記事では「oracle null 置き換え」をテーマに、NVL/COALESCEを用いた表示上の置き換え、UPDATEでの永続的な置き換え、さらには実務での注意点を網羅します。
記事のポイント
- OracleのNULLは「不明値」。空文字もNULL扱い。
- 表示置き換えはNVL/COALESCE/CASEを使う。
- UPDATEでの更新は
WHERE col IS NULL
を指定。- 空文字=NULLの仕様を理解することが重要。
oracleのnull置き換え
NULLはデータベースにおいて「不明/未定義」を意味する特別な値です。数値型・日付型・文字列型すべてで発生し得ます。
- Oracleでは空文字(”)もNULLとみなされる点に注意。PostgreSQLやMySQLでは空文字とNULLは区別されるため、移植性を考えると挙動を正確に理解することが重要です。
- 比較演算(=,
<>
)ではNULLを判定できないため、必ずIS NULL
/IS NOT NULL
を使います。
NULLを画面やレポートに出すと「空欄」になり、ユーザーに誤解を与えることがあります。そのため、表示上の置き換えが必須です。
実際のテーブル定義例
事前登録データ(DDL)
-- employeesテーブル(人事情報)-- DROP TABLE employees PURGE;
CREATE TABLE employees ( emp_id NUMBER(6) PRIMARY KEY, first_name VARCHAR2(50), last_name VARCHAR2(50), phone VARCHAR2(20), salary NUMBER(10,2), hire_date DATE);
INSERT INTO employees (emp_id, first_name, last_name, phone, salary, hire_date) VALUES(1001, 'Taro', 'Yamada', NULL, 300000, DATE '2020-04-01');INSERT INTO employees (emp_id, first_name, last_name, phone, salary, hire_date) VALUES(1002, 'Hanako', 'Suzuki', '09012345678', NULL, DATE '2021-01-15');INSERT INTO employees (emp_id, first_name, last_name, phone, salary, hire_date) VALUES(1003, 'Ken', 'Tanaka', '', 500000, NULL);INSERT INTO employees (emp_id, first_name, last_name, phone, salary, hire_date) VALUES(1004, 'Taro', NULL, '08000000000', 400000, DATE '2022-03-01');
COMMIT;
-- contactsテーブル(連絡先情報)-- DROP TABLE contacts PURGE;
CREATE TABLE contacts ( contact_id NUMBER(6) PRIMARY KEY, name VARCHAR2(100), email VARCHAR2(100), phone VARCHAR2(20));
INSERT INTO contacts (contact_id, name, email, phone) VALUES(2001, 'Sato Ichiro', NULL, '08099998888');INSERT INTO contacts (contact_id, name, email, phone) VALUES(2002, 'Miyamoto Kana', 'kana@example.com', NULL);INSERT INTO contacts (contact_id, name, email, phone) VALUES(2003, 'Kobayashi Jun', NULL, NULL);COMMIT;
-- ordersテーブル(注文情報)-- DROP TABLE orders PURGE;
CREATE TABLE orders ( order_id NUMBER(6) PRIMARY KEY, customer VARCHAR2(100), discount NUMBER(5,2));
INSERT INTO orders (order_id, customer, discount) VALUES(3001, 'Client A', NULL);INSERT INTO orders (order_id, customer, discount) VALUES(3002, 'Client B', 10);INSERT INTO orders (order_id, customer, discount) VALUES(3003, 'Client C', NULL);COMMIT;
事前登録データ(テーブル)
employeesテーブル
EMP_ID | FIRST_NAME | LAST_NAME | PHONE | SALARY | HIRE_DATE |
---|---|---|---|---|---|
1001 | Taro | Yamada | 未登録 | 300000.00 | 2020/04/01 0:00:00 |
1002 | Hanako | Suzuki | 09012345678 | NULL | 2021/01/15 0:00:00 |
1003 | Ken | Tanaka | 未登録 | 500000.00 | NULL |
1004 | Taro | NULL | 08000000000 | 400000.00 | 2022/03/01 0:00:00 |
contactsテーブル
CONTACT_ID | NAME | PHONE | |
---|---|---|---|
2001 | Sato Ichiro | NULL | 08099998888 |
2002 | Miyamoto Kana | kana@example.com | NULL |
2003 | Kobayashi Jun | NULL | NULL |
ordersテーブル
ORDER_ID | CUSTOMER | DISCOUNT |
---|---|---|
3001 | Client A | NULL |
3002 | Client B | 10.00 |
3003 | Client C | NULL |
このような典型的な人事テーブルで、電話番号などがNULLの場合に既定値を設定するケースを想定します。
NVLによるnullの置き換え
NVL(expr1, expr2)-- expr1 : 評価対象の式(NULL かもしれない値)-- expr2 : expr1 が NULL のときに返す値
SELECT NVL(phone, '未登録') AS phoneFROM employees;
実行結果
PHONE |
---|
未登録 |
09012345678 |
未登録 |
08000000000 |
NULLなら第2引数の値を返します。Oracle固有関数で、簡潔に書けますが型変換に注意が必要です。
NVL2によるnullの置き換え
NVL2(expr, value_if_not_null, value_if_null)-- expr : 評価対象の式-- value_if_not_null : expr が NULLでない場合に返す値-- value_if_null : expr が NULLの場合に返す値
NVL が「NULLなら置き換え」だけなのに対して、NVL2 は「NULLと非NULLの両方に対応できる」のが特徴です。
SELECT NVL2(last_name, first_name, '(空)')FROM employees;
実行結果
NVL2(LAST_NAME,FIRST_NAME,‘(空)‘) |
---|
Taro |
Hanako |
Ken |
(空) |
非NULLなら第2引数を、NULLなら第3引数を返します。条件分岐が明示できるため便利です。
COALESCEによるnullの置き換え
COALESCE(expr1, expr2, expr3, ... , exprN)-- 左から順番に評価され、最初に見つかったNULLでない値を返します。-- すべてがNULLなら NULLを返す。
SELECT COALESCE(email, phone, '不明')FROM contacts;
実行結果
COALESCE(EMAIL,PHONE,‘不明’) |
---|
08099998888 |
kana@example.com |
不明 |
複数の候補から最初に見つかった非NULL値を返します。ANSI標準で移植性が高いのが特徴です。
CASE式によるnullの置き換え
SELECT CASE WHEN discount IS NULL THEN 0 ELSE discount ENDFROM orders;
実行結果
CASEWHENDISCOUNTISNULLTHEN0ELSEDISCOUNTEND |
---|
0 |
10 |
0 |
discountがNULLの場合は0を返却します。 条件分岐を自由に書けるため、複雑な業務ルールや型が混在する場面で役立ちます。
実データを更新してNULLを置き換える
UPDATEの基本形
UPDATE employeesSET phone = '未登録'WHERE phone IS NULL;
更新前(SELECT * FROM employees;
)
EMP_ID | FIRST_NAME | LAST_NAME | PHONE | SALARY | HIRE_DATE |
---|---|---|---|---|---|
1001 | Taro | Yamada | NULL | 300000.00 | 2020/04/01 0:00:00 |
1002 | Hanako | Suzuki | 09012345678 | NULL | 2021/01/15 0:00:00 |
1003 | Ken | Tanaka | NULL | 500000.00 | NULL |
1004 | Taro | NULL | 08000000000 | 400000.00 | 2022/03/01 0:00:00 |
更新後(SELECT * FROM employees;
)
EMP_ID | FIRST_NAME | LAST_NAME | PHONE | SALARY | HIRE_DATE |
---|---|---|---|---|---|
1001 | Taro | Yamada | 未登録 | 300000.00 | 2020/04/01 0:00:00 |
1002 | Hanako | Suzuki | 09012345678 | NULL | 2021/01/15 0:00:00 |
1003 | Ken | Tanaka | 未登録 | 500000.00 | NULL |
1004 | Taro | NULL | 08000000000 | 400000.00 | 2022/03/01 0:00:00 |
これでphone列がNULLの行に「未登録」を設定します。WHEREを必ず付与して不要な更新を避けましょう。
oracle null 置き換え — データ型別の活用例
-- 数値型: NULLを0に置き換えて集計SELECT SUM(NVL(salary,0)) FROM employees;
-- 日付型: NULLを特定日付に置き換えるSELECT NVL(hire_date, DATE '2000-01-01') FROM employees;
-- 文字列結合: NULLを空文字に置き換えSELECT NVL(first_name,'') || ' ' || NVL(last_name,'') AS full_nameFROM employees;
空文字とNULLの違い
- Oracleでは空文字 = NULL。INSERTで”を入れてもNULLとして格納されます。
- ユニーク制約ではNULLは「異なる値」と見なされるため、複数行にNULLを入れても違反しません。
- しかしアプリが空文字とNULLを区別していると、整合性問題を引き起こします。
oracle null 置き換え — よくあるFAQ
Q. NVLとCOALESCEの違いは?
項目 | NVL | COALESCE |
---|---|---|
引数の数 | 2つのみ | 2つ以上(可変長) |
処理内容 | expr1がNULLならexpr2を返す | 最初にNULLでない値を返す |
-
NVLを使う場合
- 単純に「NULLをデフォルト値に置き換えたい」とき
- 例:給与、手数料、在庫数のNULLを0にする
-
COALESCEを使う場合
- 複数の候補カラムからNULLでない値を優先的に取得したいとき
- 例:電話番号(携帯 → 自宅 → 会社)、住所(現住所 → 本籍 → 登録住所)
Q. 実データのNULLを埋めるべき? → UI表示だけなら関数利用で十分。マスタデータや参照整合性が必要な場合はUPDATEを推奨。
Q. 空文字を残したい場合は? → Oracleでは不可能。代替として特殊文字(例:’ ‘や’-‘)を利用する設計が必要。
OracleにおけるNULL置き換えのまとめ
- 表示置き換えは
NVL
/COALESCE
を使う。 - 永続化するなら
UPDATE ... WHERE col IS NULL
をバッチ処理で。 - 空文字とNULLの違いを理解して設計する。
- 「NULL」「0」「未登録」を混同しないよう要件を整理する。
以上で本記事の解説を終わります。
よいITライフを!