【Oracle】数値をゼロ埋め(ゼロパディング)する方法|TO_CHAR・LPAD・FM修飾子・桁超過対策・実務パターンまで解説

【Oracle】数値をゼロ埋め(ゼロパディング)する方法|TO_CHAR・LPAD・FM修飾子・桁超過対策・実務パターンまで解説 Oracle

Oracle で「数値 7007 と表示したい」「社員番号を 5 桁ゼロ埋めで統一したい」といった場面は頻繁にあります。Oracle ではゼロ埋め(ゼロパディング)に TO_CHAR 関数と LPAD 関数の2 つの方法が使えますが、それぞれに落とし穴があります。

本記事では、TO_CHAR の '0' 書式と LPAD の使い方を比較しながら、先頭スペース問題桁数を超えたときの ### 問題負の数のゼロ埋め、そして社員番号・伝票番号・連番生成などの実務パターンまで体系的に解説します。

この記事でわかること
・TO_CHAR の ‘0’ 書式で数値をゼロ埋めする方法
・LPAD 関数で文字列としてゼロ埋めする方法
・TO_CHAR と LPAD の違い(先頭スペース・桁超過時の動作・型変換)
・FM 修飾子で先頭スペースを除去する方法
・桁数を超えた場合の ### 問題と対策
・負の数のゼロ埋め
・社員番号・伝票番号・日付連番・バーコードの実務パターン
スポンサーリンク

TO_CHAR でゼロ埋めする

SQL(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 の結果に先頭スペースが付く
TO_CHAR(7, '00000') の結果は ' 00007'(先頭にスペース 1 文字)です。これは正の数の符号領域(正のときはスペース、負のときは -)を確保するための Oracle の仕様です。先頭スペースを除去するには FM 修飾子を使います(後述)。

FM 修飾子で先頭スペースを除去する

SQL(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;
FM は「常に付ける」がベストプラクティス
ゼロ埋めの場面で先頭スペースが必要になることはほぼありません。TO_CHAR(n, 'FM00000') のように FM を常に付ける書き方を推奨します。

書式モデルの ‘0’ と ‘9’ の違い

書式 値がない桁の表示 使用例 結果(入力: 42)
‘0’ 0 で埋める(ゼロ埋め) TO_CHAR(42, ‘FM00000’) 00042
‘9’ スペースで埋める(空白埋め) TO_CHAR(42, ‘FM99999’) 42
SQL(’0′ と ‘9’ の比較)
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が消える原因と表示する方法」で詳しく解説しています。

桁数を超えた場合の ### 問題

SQL(桁数オーバーで ### になる)
-- 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)関数は、文字列の左側を指定した文字で埋めて固定長にする関数です。ゼロ埋めにも使えます。

SQL(LPAD 基本)
-- 構文: 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
LPAD のメリット
・先頭スペースが付かない(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 が安全(符号の位置を制御できる)

負の数のゼロ埋め

SQL(負の数のゼロ埋め)
-- 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
負の数のゼロ埋めは TO_CHAR を使う
LPAD で負の数をゼロ埋めすると、0-42 のようにマイナス記号の前にゼロが付きます。負の数を扱う場合は TO_CHAR(n, 'FM00000') を使えばマイナス記号が正しく先頭に付きます。

実務パターン集

パターン①:社員番号・顧客番号を 5 桁ゼロ埋めで表示

SQL(番号のゼロ埋め表示)
-- 社員番号を 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;

パターン②:日付 + 連番で伝票番号を生成

SQL(伝票番号の生成)
-- 伝票番号: 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;

パターン③:月・日のゼロ埋め(日付の要素を個別に取得)

SQL(月・日のゼロ埋め)
-- 月と日を個別にゼロ埋め表示
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 で既存データをゼロ埋め

SQL(既存データのゼロ埋め 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 時にゼロ埋めした値を格納

SQL(INSERT 時のゼロ埋め)
-- シーケンスの値をゼロ埋めして VARCHAR2 列に格納
INSERT INTO products (product_id, product_code, product_name)
VALUES (
    seq_product.NEXTVAL,
    'PRD' || TO_CHAR(seq_product.CURRVAL, 'FM00000'),  -- PRD00001
    '新商品'
);

よくある質問

QTO_CHAR でゼロ埋めすると先頭にスペースが付きます
ATO_CHAR はデフォルトで正の数の符号領域(スペース 1 文字)を確保します。FM(Fill Mode)修飾子を付けてください。TO_CHAR(42, 'FM00000') で先頭スペースなしの 00042 が返ります。
QTO_CHAR の結果が ### になります
A書式モデルの桁数より値の桁数が大きい場合に ###### が返ります。書式モデルの桁数を増やしてください。たとえば 6 桁の値には 'FM000000' 以上を指定します。桁超過を防ぎたい場合は LPAD を使うと、元の値がそのまま返ります。
QTO_CHAR と LPAD はどちらを使うべきですか?
ANUMBER 型を扱い、負の数の符号制御や書式の統一が必要なら TO_CHAR。VARCHAR2 型の既存文字列を固定桁に揃えるなら LPAD。桁超過で ### になるのを避けたいなら LPAD。迷ったら TO_CHAR(FM 付き)を使い、問題があれば LPAD に切り替えるのが実用的です。
QNULL の場合にゼロ埋めの結果はどうなりますか?
ATO_CHAR(NULL, 'FM00000')LPAD(NULL, 5, '0')NULL を返します。NULL をゼロ埋めしたい(例: 00000 にする)場合は TO_CHAR(NVL(n, 0), 'FM00000') のように NVL で先にデフォルト値を設定します。
Qゼロ埋めした値を NUMBER 型に戻すとゼロが消えます
ANUMBER 型は「数値」なので先頭のゼロを保持しません。TO_NUMBER('00042')42 になります。先頭ゼロを保持したい場合は文字列型(VARCHAR2)で格納してください。NUMBER 型に戻すのはあくまで計算時のみにし、表示用は文字列で管理するのが定石です。
Qゼロ以外の文字(スペースやアスタリスク)で埋めるには?
ALPAD なら第 3 引数を変えるだけです。LPAD('42', 5, '*')***42LPAD('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 日付フォーマット完全ガイド」も併せて参照してください。