Oracle で SELECT 1.50 FROM DUAL を実行すると 1.5 と表示され、末尾の 0 が消えてしまいます。これは Oracle の NUMBER 型の仕様です。本記事では なぜ 0 が消えるのか、そして TO_CHAR の書式モデルで 0 を強制表示する方法を体系的に解説します。
- 小数点以下の末尾ゼロが消える原因(NUMBER 型の仕様)
- TO_CHAR の
9と0の違い - 末尾ゼロを保持して表示する方法(
1.50、1.500など) - 小数点前のゼロが消える問題(
0.5→.5)の解決 - FM 修飾子との組み合わせ
- NLS_NUMERIC_CHARACTERS による小数点記号の変更
なぜ 0 が消えるのか
Oracle の NUMBER 型は内部的に 有効桁だけ を保持します。末尾のゼロは有効桁ではないため、格納・演算ともに自動的に除去されます。
-- 末尾ゼロが消える例 SELECT 1.50 FROM DUAL; -- 結果: 1.5 SELECT 1.500 FROM DUAL; -- 結果: 1.5 SELECT 1.5000 FROM DUAL; -- 結果: 1.5 SELECT 0.50 FROM DUAL; -- 結果: .5 ← 先頭ゼロも消える! SELECT 100.00 FROM DUAL; -- 結果: 100 -- 計算結果でも同様 SELECT 10 / 4 FROM DUAL; -- 結果: 2.5(2.50 にはならない) SELECT AVG(price) FROM products; -- 結果は桁数不定
0.5 が .5 と表示されるケースも同じ仕様です。小数点前の 0 も「不要な桁」として省略されます。アプリケーション表示では違和感を与えるため、TO_CHAR での明示的な制御が必要です。
TO_CHAR の書式モデル基本
数値の表示を制御するには TO_CHAR(数値, '書式文字列') を使います。書式文字列の各文字が表示形式を決定します。
| 書式文字 | 意味 | ゼロの扱い |
|---|---|---|
9 |
数字 1 桁(値がなければスペース) | 先頭ゼロ・末尾ゼロともに表示しない |
0 |
数字 1 桁(値がなければ 0 を表示) | ゼロを強制表示する |
. |
小数点の位置 | — |
, |
桁区切りカンマの位置 | — |
FM |
先頭・末尾のスペースとゼロを除去 | 末尾ゼロを 除去(0 と逆効果) |
「この桁は必ず表示したい」位置には
0 を使います。「値があれば表示、なければ空白にしたい」位置には
9 を使います。実用上は 整数部に 9、小数部に 0 というパターンが最も多いです。
末尾ゼロを表示する
小数点以下を固定桁数で表示
-- 小数第 2 位まで固定表示(末尾ゼロを保持) SELECT TO_CHAR(1.5, '9990.00') FROM DUAL; -- 結果: ' 1.50' SELECT TO_CHAR(1.567, '9990.00') FROM DUAL; -- 結果: ' 1.57' ← 四捨五入 SELECT TO_CHAR(100, '9990.00') FROM DUAL; -- 結果: ' 100.00' SELECT TO_CHAR(0.5, '9990.00') FROM DUAL; -- 結果: ' 0.50' ← 先頭ゼロも表示 -- TRIM で先頭スペースを除去 SELECT TRIM(TO_CHAR(1.5, '9990.00')) FROM DUAL; -- 結果: '1.50' SELECT TRIM(TO_CHAR(100, '9990.00')) FROM DUAL; -- 結果: '100.00' SELECT TRIM(TO_CHAR(0.5, '9990.00')) FROM DUAL; -- 結果: '0.50' -- 小数第 3 位まで固定表示 SELECT TRIM(TO_CHAR(1.5, '9990.000')) FROM DUAL; -- 結果: '1.500' SELECT TRIM(TO_CHAR(3.14, '9990.000')) FROM DUAL; -- 結果: '3.140'
先頭ゼロも表示する(0.5 を .5 にしない)
-- 書式の整数部に '0' を使うと先頭ゼロが表示される SELECT TO_CHAR(0.5, '0.00') FROM DUAL; -- 結果: ' 0.50' ← 先頭ゼロあり SELECT TO_CHAR(0.5, '9.99') FROM DUAL; -- 結果: ' .50' ← 先頭ゼロなし(スペースに) SELECT TO_CHAR(0.05, '0.000') FROM DUAL; -- 結果: ' 0.050' SELECT TO_CHAR(0.05, '9.999') FROM DUAL; -- 結果: ' .050'
整数部
9990 の最後の 0 がポイントです。0 は「その桁が 0 のときも必ず数字を表示する」指定のため、値が 0.5 のときの整数部が 空白にならず 0 と表示されます。これにより
0.5 → 0.50(.50 ではなく)と表示されます。
FM 修飾子との関係
FM(Fill Mode)は余分なスペースや末尾ゼロを除去する修飾子です。0 書式と組み合わせると挙動が変わるので注意が必要です。
-- FM なし:先頭スペースが付く SELECT TO_CHAR(1.5, '9990.00') FROM DUAL; -- 結果: ' 1.50'(先頭にスペース) -- FM あり:先頭スペースは除去されるが末尾ゼロも除去される SELECT TO_CHAR(1.5, 'FM9990.00') FROM DUAL; -- 結果: '1.5' ← 末尾ゼロが消える! SELECT TO_CHAR(1.0, 'FM9990.00') FROM DUAL; -- 結果: '1' ← 小数点ごと除去 -- 末尾ゼロを保持したい場合は FM を使わず TRIM を使う SELECT TRIM(TO_CHAR(1.5, '9990.00')) FROM DUAL; -- 結果: '1.50'(スペースなし・ゼロあり)
末尾ゼロを表示したいのに
FM を付けると、0 書式で指定したゼロが除去されてしまいます。先頭スペースを除去したい場合は
FM ではなく TRIM(TO_CHAR(...)) を使ってください。
実務パターン集
金額表示(1,500.00 形式)
-- 価格を小数第 2 位まで固定表示(カンマ区切りあり) SELECT product_name, price, TRIM(TO_CHAR(price, '999,999,990.00')) AS price_str FROM products; -- 例: price=1500 → '1,500.00' -- 例: price=1500.5 → '1,500.50' -- 例: price=0.99 → '0.99' -- 円マーク付き SELECT product_name, '¥' || TRIM(TO_CHAR(price, '999,999,990.00')) AS price_jpy FROM products;
パーセント表示(1.50% 形式)
-- 比率を小数第 2 位まで固定表示してパーセント表記 SELECT category, ratio, TRIM(TO_CHAR(ratio * 100, '990.00')) || '%' AS ratio_pct FROM category_stats; -- 例: ratio=0.015 → '1.50%' -- 例: ratio=0.1 → '10.00%' -- 例: ratio=1.0 → '100.00%'
計測値・科学データ(桁数固定)
-- 小数第 3 位まで固定(センサーデータ・計測値など) SELECT sensor_id, measured_value, TRIM(TO_CHAR(measured_value, '9990.000')) AS value_str FROM sensor_data; -- 例: measured_value=1.5 → '1.500' -- 例: measured_value=12.34 → '12.340' -- 例: measured_value=0.1 → '0.100'
整数なら小数点なし・小数なら 2 桁固定
-- CASE で桁数を動的に切り替える
SELECT
amount,
CASE
WHEN amount = TRUNC(amount)
THEN TO_CHAR(amount, 'FM999,990') -- 整数なら小数点なし
ELSE TRIM(TO_CHAR(amount, '999,990.00')) -- 小数なら 2 桁固定
END AS amount_str
FROM transactions;
-- 例: amount=1000 → '1,000'
-- 例: amount=1000.5 → '1,000.50'
NLS_NUMERIC_CHARACTERS の影響
国際化対応の環境では小数点やカンマの記号が変わる場合があります。NLS_NUMERIC_CHARACTERS パラメータで制御できます。
-- デフォルト(日本・米国): 小数点=「.」、桁区切り=「,」 SELECT TO_CHAR(1234.5, '9,990.00') FROM DUAL; -- 結果: '1,234.50' -- NLS に依存しない書き方(G=桁区切り、D=小数点 → NLS設定に従う) SELECT TO_CHAR(1234.5, '9G990D00') FROM DUAL; -- セッション単位で NLS を変更する場合 ALTER SESSION SET NLS_NUMERIC_CHARACTERS = ',.'; SELECT TO_CHAR(1234.5, '9G990D00') FROM DUAL; -- 結果: '1.234,50'(ヨーロッパ式)
Oracle の NUMBER 型から Java/Python などで値を取得すると、言語側でも末尾ゼロが除去されることがあります。
表示レイヤーで固定桁数にする場合は DB 側で
TO_CHAR しておくか、アプリ側で String.format("%.2f", value)(Java)や f"{value:.2f}"(Python)等のフォーマットを行ってください。
よくある質問(FAQ)
NUMBER(10,2) と定義すると 格納時に小数第 2 位に丸め られますが、表示上の末尾ゼロは保証されません。SELECT で取得した値は NUMBER 型のため、1.50 は 1.5 と表示されます。
末尾ゼロを表示するには TRIM(TO_CHAR(col, '9990.00')) が必要です。型定義だけでは表示を制御できません。
Oracle の TO_CHAR は正数に対して符号位置として先頭にスペースを 1 文字確保します(負数のマイナス符号と桁を揃えるため)。これは仕様です。
スペースを除去するには TRIM(TO_CHAR(...)) を使います。FM 修飾子でも除去できますが、末尾ゼロも消えてしまうため、末尾ゼロを保持したい場合は TRIM を使ってください。
SELECT TRIM(TO_CHAR(1.5, '9990.00')) FROM DUAL; -- 結果: '1.50'(スペースなし)
整数部の最大桁数以上の 9(または 0)を並べれば問題ありません。足りない場合は # が表示されて値が見えなくなります。多い分には先頭スペースになるだけなので、余裕を持たせておくほうが安全です。
SELECT TO_CHAR(12345, '999.00') FROM DUAL; -- 結果: '###.00' ← 桁が足りない SELECT TO_CHAR(12345, '99999.00') FROM DUAL; -- 結果: '12345.00' ← OK
CAST(1.50 AS VARCHAR2(20)) は書式モデルを指定できないため、末尾ゼロは除去された '1.5' になります。書式を制御できるのは TO_CHAR だけです。
NUMBER 型のカラムには末尾ゼロを保存できません。UPDATE t SET price = 1.50 としても、格納されるのは 1.5 です。
「1.50 という文字列として保存したい」なら VARCHAR2 型のカラムに格納するか、表示時に TO_CHAR で変換する設計にしてください。ただし金額計算には NUMBER 型を使うのが基本です。
まとめ
| やりたいこと | 書式例 | 入力 | 出力 |
|---|---|---|---|
| 末尾ゼロを 2 桁固定 | TRIM(TO_CHAR(n, '9990.00')) |
1.5 | 1.50 |
| 末尾ゼロを 3 桁固定 | TRIM(TO_CHAR(n, '9990.000')) |
1.5 | 1.500 |
| 先頭ゼロも表示(0.5 → 0.50) | TRIM(TO_CHAR(n, '0.00')) |
0.5 | 0.50 |
| カンマ区切り + 2 桁固定 | TRIM(TO_CHAR(n, '999,990.00')) |
1500.5 | 1,500.50 |
| 先頭スペースを除去するだけ | TRIM(TO_CHAR(n, '9990.99')) |
1.5 | 1.5 |
| 末尾ゼロを除去(デフォルト動作) | TO_CHAR(n) または FM 付き |
1.50 | 1.5 |
Oracle の NUMBER 型は末尾ゼロを保持しない仕様です。表示上のゼロを保持するには TO_CHAR の書式モデルで 0 を使って固定桁数にするのが確実な方法です。FM は末尾ゼロを除去してしまうため、先頭スペースを除去したい場合は TRIM を組み合わせてください。

