Oracle で「数値 7 を 007 と表示したい」「社員番号を 5 桁ゼロ埋めで統一したい」といった場面は頻繁にあります。Oracle ではゼロ埋め(ゼロパディング)に TO_CHAR 関数と LPAD 関数の2 つの方法が使えますが、それぞれに落とし穴があります。
本記事では、TO_CHAR の '0' 書式と LPAD の使い方を比較しながら、先頭スペース問題、桁数を超えたときの ### 問題、負の数のゼロ埋め、そして社員番号・伝票番号・連番生成などの実務パターンまで体系的に解説します。
・TO_CHAR の ‘0’ 書式で数値をゼロ埋めする方法
・LPAD 関数で文字列としてゼロ埋めする方法
・TO_CHAR と LPAD の違い(先頭スペース・桁超過時の動作・型変換)
・FM 修飾子で先頭スペースを除去する方法
・桁数を超えた場合の ### 問題と対策
・負の数のゼロ埋め
・社員番号・伝票番号・日付連番・バーコードの実務パターン
TO_CHAR でゼロ埋めする
-- '0' は「その桁に値がなければ 0 で埋める」 SELECT TO_CHAR(7, '00000') AS result FROM dual; -- 00007 SELECT TO_CHAR(42, '00000') AS result FROM dual; -- 00042 SELECT TO_CHAR(12345, '00000') AS result FROM dual; -- 12345 -- 3 桁ゼロ埋め SELECT TO_CHAR(7, '000') AS result FROM dual; -- 007 -- 8 桁ゼロ埋め SELECT TO_CHAR(123, '00000000') AS result FROM dual; -- 00000123
TO_CHAR(7, '00000') の結果は ' 00007'(先頭にスペース 1 文字)です。これは正の数の符号領域(正のときはスペース、負のときは -)を確保するための Oracle の仕様です。先頭スペースを除去するには FM 修飾子を使います(後述)。FM 修飾子で先頭スペースを除去する
-- FM なし: 先頭にスペースが付く SELECT '[' || TO_CHAR(7, '00000') || ']' AS result FROM dual; -- 結果: [ 00007] ← 先頭にスペース -- FM あり: 先頭スペースを除去 SELECT '[' || TO_CHAR(7, 'FM00000') || ']' AS result FROM dual; -- 結果: [00007] ← スペースなし -- 実用的な書き方(FM は常に付けることを推奨) SELECT TO_CHAR(employee_id, 'FM00000') AS emp_code FROM employees;
ゼロ埋めの場面で先頭スペースが必要になることはほぼありません。
TO_CHAR(n, 'FM00000') のように FM を常に付ける書き方を推奨します。書式モデルの ‘0’ と ‘9’ の違い
| 書式 | 値がない桁の表示 | 使用例 | 結果(入力: 42) |
|---|---|---|---|
| ‘0’ | 0 で埋める(ゼロ埋め) | TO_CHAR(42, ‘FM00000’) | 00042 |
| ‘9’ | スペースで埋める(空白埋め) | TO_CHAR(42, ‘FM99999’) | 42 |
SELECT
TO_CHAR(42, 'FM00000') AS zero_fill, -- 00042(ゼロ埋め)
TO_CHAR(42, 'FM99999') AS space_fill -- 42(ゼロなし)
FROM dual;
-- 混合: 整数部はゼロ埋め、小数部はスペース
SELECT TO_CHAR(42.5, 'FM00000.99') AS result FROM dual; -- 00042.5
-- 整数部はスペース埋め、小数部はゼロ埋め
SELECT TO_CHAR(42.5, 'FM99999.00') AS result FROM dual; -- 42.50
小数点以下の末尾ゼロの表示方法については「小数点以下の0が消える原因と表示する方法」で詳しく解説しています。
桁数を超えた場合の ### 問題
-- 5 桁の書式に 6 桁の値を入れると ### になる SELECT TO_CHAR(123456, 'FM00000') AS result FROM dual; -- 結果: ###### ← 桁数不足で表示できない -- 対策: 十分な桁数を確保する SELECT TO_CHAR(123456, 'FM000000') AS result FROM dual; -- 結果: 123456
TO_CHAR の書式モデルに指定した桁数より値の桁数が大きいと、Oracle は
###### を返します(エラーではない)。対策は書式モデルの桁数を増やすことです。データの最大桁数を考慮して余裕を持った桁数を設定してください。LPAD でゼロ埋めする
LPAD(Left Pad)関数は、文字列の左側を指定した文字で埋めて固定長にする関数です。ゼロ埋めにも使えます。
-- 構文: LPAD(文字列, 全体の文字数, 埋め文字)
-- 5 桁ゼロ埋め
SELECT LPAD('7', 5, '0') AS result FROM dual; -- 00007
SELECT LPAD('42', 5, '0') AS result FROM dual; -- 00042
SELECT LPAD('12345', 5, '0') AS result FROM dual; -- 12345
-- 数値を LPAD に渡す場合(暗黙変換が発生)
SELECT LPAD(7, 5, '0') AS result FROM dual; -- 00007
SELECT LPAD(42, 5, '0') AS result FROM dual; -- 00042
-- TO_CHAR で明示的に変換してから LPAD(推奨)
SELECT LPAD(TO_CHAR(42), 5, '0') AS result FROM dual; -- 00042
・先頭スペースが付かない(FM 不要)
・桁数を超えても ### にならない(元の文字列がそのまま返る)
・文字列型のカラムにもそのまま使える
・ゼロ以外の文字(スペース、アスタリスク等)でも埋められる
TO_CHAR と LPAD の違い
| 項目 | TO_CHAR(n, ‘FM00000’) | LPAD(TO_CHAR(n), 5, ‘0’) |
|---|---|---|
| 先頭スペース | FM なしで付く(FM で除去可) | 付かない |
| 桁数超過時 | ### になる | 元の値がそのまま返る(切り詰めなし) |
| 入力型 | NUMBER 型のみ | 文字列型にも使える |
| 負の数 | -00042(符号が自動付与) |
0-42 になることがある(注意) |
| NULL 入力 | NULL を返す | NULL を返す |
| 小数の扱い | 書式で小数桁も制御可能 | 文字列操作なので小数点もそのまま |
| 可読性 | 書式モデルで意図が明確 | やや冗長 |
・NUMBER 型の数値をゼロ埋め表示 →
TO_CHAR(n, 'FM00000') が自然・VARCHAR2 型の文字列を固定桁に揃える →
LPAD が適切・桁数超過で ### にしたくない →
LPAD が安全・負の数を扱う →
TO_CHAR が安全(符号の位置を制御できる)負の数のゼロ埋め
-- TO_CHAR: 符号が自動的に先頭に付く
SELECT TO_CHAR(-42, 'FM00000') AS result FROM dual; -- -00042
SELECT TO_CHAR(-42, 'FMS00000') AS result FROM dual; -- -00042(S=符号を常に表示)
SELECT TO_CHAR(42, 'FMS00000') AS result FROM dual; -- +00042(正の場合も+が付く)
-- LPAD: 符号の位置に注意が必要
SELECT LPAD(TO_CHAR(-42), 6, '0') AS result FROM dual; -- 00-42 ← 意図しない結果
-- LPAD で負の数を正しくゼロ埋めするには工夫が必要
SELECT
CASE WHEN -42 < 0
THEN '-' || LPAD(TO_CHAR(ABS(-42)), 5, '0')
ELSE LPAD(TO_CHAR(-42), 5, '0')
END AS result
FROM dual;
-- 結果: -00042
LPAD で負の数をゼロ埋めすると、
0-42 のようにマイナス記号の前にゼロが付きます。負の数を扱う場合は TO_CHAR(n, 'FM00000') を使えばマイナス記号が正しく先頭に付きます。実務パターン集
パターン①:社員番号・顧客番号を 5 桁ゼロ埋めで表示
-- 社員番号を 5 桁ゼロ埋めで表示
SELECT
employee_id,
TO_CHAR(employee_id, 'FM00000') AS emp_code
FROM employees;
-- employee_id=7 → emp_code='00007'
-- employee_id=142 → emp_code='00142'
-- LPAD 版
SELECT
employee_id,
LPAD(employee_id, 5, '0') AS emp_code
FROM employees;
パターン②:日付 + 連番で伝票番号を生成
-- 伝票番号: YYYYMMDD + 4桁連番
SELECT
TO_CHAR(SYSDATE, 'YYYYMMDD')
|| TO_CHAR(seq_invoice.NEXTVAL, 'FM0000') AS invoice_no
FROM dual;
-- 結果例: 202603280001, 202603280002, ...
-- シーケンスなしで ROW_NUMBER を使う方法
SELECT
TO_CHAR(order_date, 'YYYYMMDD')
|| TO_CHAR(ROW_NUMBER() OVER (PARTITION BY order_date ORDER BY order_id), 'FM0000')
AS order_no
FROM orders;
パターン③:月・日のゼロ埋め(日付の要素を個別に取得)
-- 月と日を個別にゼロ埋め表示
SELECT
TO_CHAR(SYSDATE, 'YYYY') AS year,
TO_CHAR(SYSDATE, 'MM') AS month, -- 常に 2 桁(01〜12)
TO_CHAR(SYSDATE, 'DD') AS day, -- 常に 2 桁(01〜31)
TO_CHAR(SYSDATE, 'HH24') AS hour, -- 常に 2 桁(00〜23)
TO_CHAR(SYSDATE, 'MI') AS minute, -- 常に 2 桁(00〜59)
TO_CHAR(SYSDATE, 'SS') AS second -- 常に 2 桁(00〜59)
FROM dual;
-- 日付書式 MM/DD/HH24 は元からゼロ埋め
-- FM を付けるとゼロが消える: FMMM → '3'(3月)
日付フォーマットの詳細は「TO_CHAR / TO_DATE 日付フォーマット完全ガイド」を参照してください。
パターン④:UPDATE で既存データをゼロ埋め
-- VARCHAR2 型の code 列を 8 桁ゼロ埋めに統一 UPDATE products SET product_code = LPAD(product_code, 8, '0') WHERE LENGTH(product_code) < 8; -- NUMBER 型の列を文字列としてゼロ埋めした列に変換する場合 -- まず列を追加 → UPDATE → 元列を DROP ALTER TABLE products ADD (product_code_str VARCHAR2(8)); UPDATE products SET product_code_str = LPAD(TO_CHAR(product_code_num), 8, '0'); COMMIT;
パターン⑤:INSERT 時にゼロ埋めした値を格納
-- シーケンスの値をゼロ埋めして VARCHAR2 列に格納
INSERT INTO products (product_id, product_code, product_name)
VALUES (
seq_product.NEXTVAL,
'PRD' || TO_CHAR(seq_product.CURRVAL, 'FM00000'), -- PRD00001
'新商品'
);
よくある質問
FM(Fill Mode)修飾子を付けてください。TO_CHAR(42, 'FM00000') で先頭スペースなしの 00042 が返ります。###### が返ります。書式モデルの桁数を増やしてください。たとえば 6 桁の値には 'FM000000' 以上を指定します。桁超過を防ぎたい場合は LPAD を使うと、元の値がそのまま返ります。TO_CHAR。VARCHAR2 型の既存文字列を固定桁に揃えるなら LPAD。桁超過で ### になるのを避けたいなら LPAD。迷ったら TO_CHAR(FM 付き)を使い、問題があれば LPAD に切り替えるのが実用的です。TO_CHAR(NULL, 'FM00000') も LPAD(NULL, 5, '0') も NULL を返します。NULL をゼロ埋めしたい(例: 00000 にする)場合は TO_CHAR(NVL(n, 0), 'FM00000') のように NVL で先にデフォルト値を設定します。TO_NUMBER('00042') は 42 になります。先頭ゼロを保持したい場合は文字列型(VARCHAR2)で格納してください。NUMBER 型に戻すのはあくまで計算時のみにし、表示用は文字列で管理するのが定石です。LPAD なら第 3 引数を変えるだけです。LPAD('42', 5, '*') → ***42、LPAD('42', 5, ' ') → 42。TO_CHAR ではゼロ埋め(0)またはスペース埋め(9)のみ対応です。任意文字の埋めには LPAD を使ってください。まとめ
Oracle でのゼロ埋め方法の要点をまとめます。
| やりたいこと | 推奨方法 |
|---|---|
| NUMBER 型を 5 桁ゼロ埋め表示 | TO_CHAR(n, ‘FM00000’) |
| VARCHAR2 型を 5 桁ゼロ埋め | LPAD(str, 5, ‘0’) |
| 先頭スペースを除去 | FM 修飾子を付ける: TO_CHAR(n, ‘FM00000’) |
| 桁数超過で ### にしたくない | LPAD(TO_CHAR(n), 5, ‘0’) |
| 負の数のゼロ埋め | TO_CHAR(n, ‘FM00000’) → -00042 |
| NULL を 00000 にする | TO_CHAR(NVL(n, 0), ‘FM00000’) |
| 日付 + 連番で伝票番号生成 | TO_CHAR(SYSDATE, ‘YYYYMMDD’) || TO_CHAR(seq.NEXTVAL, ‘FM0000’) |
| 既存データを一括ゼロ埋め | UPDATE t SET col = LPAD(col, 8, ‘0’) WHERE LENGTH(col) < 8 |
| アスタリスク埋めなど任意文字 | LPAD(str, 5, ‘*’) |
小数点以下の末尾ゼロ表示については「小数点以下の0が消える原因と表示する方法」、日付のフォーマットについては「TO_CHAR / TO_DATE 日付フォーマット完全ガイド」も併せて参照してください。
