web-dev-qa-db-ja.com

Oracle-数値をTO_CHARに変換すると、先頭のゼロが消えるのはなぜですか

Oracleで、先頭に0を付けた数字を文字に変換するとき、whyは先頭の数字が消えますか?このロジックはOracle固有ですか、それともSQL固有ですか?

例:

SELECT TO_CHAR(0.56) FROM DUAL;
/* Result = .56 */
34
contactmatt

Oracleが提供するデフォルトのフォーマットです。出力の先頭にゼロが必要な場合は、形式を明示的に指定する必要があります。つかいます:

SELECT TO_CHAR(0.56,'0.99') FROM DUAL;

あるいは:

SELECT TO_CHAR(.56,'0.99') FROM DUAL;

後続のゼロについても同じことが言えます。

SQL> SELECT TO_CHAR(.56,'0.990') val FROM DUAL;

VAL
------
 0.560

TO_CHAR変換関数の一般的な形式は次のとおりです。

TO_CHAR (number、 format

30
DCookie

私は、先頭または末尾なしで数値をフォーマットする方法を探していました スペース 、ピリオド、ゼロ(存在するはずの1より小さい数値の先頭のゼロを除く)。

これは、このような最も一般的な書式設定をOracleで簡単に実現できないことを不満に思っています。

でも Tom Kyteは長く複雑な回避策のみを提案した このように:

case when trunc(x)=x
    then to_char(x, 'FM999999999999999999')
    else to_char(x, 'FM999999999999999.99')
end x

しかし、私は一度だけ値に言及するより短いソリューションを見つけることができました:

rtrim(to_char(x, 'FM999999999999990.99'), '.')

これ 期待どおりに動作します すべての可能な値に対して:

select 
    to_char(num, 'FM99.99') wrong_leading_period,
    to_char(num, 'FM90.99') wrong_trailing_period,
    rtrim(to_char(num, 'FM90.99'), '.') correct
from (
  select num from (select 0.25 c1, 0.1 c2, 1.2 c3, 13 c4, -70 c5 from dual)
  unpivot (num for dummy in (c1, c2, c3, c4, c5))
) sampledata;

    | WRONG_LEADING_PERIOD | WRONG_TRAILING_PERIOD | CORRECT |
    |----------------------|-----------------------|---------|
    |                  .25 |                  0.25 |    0.25 |
    |                   .1 |                   0.1 |     0.1 |
    |                  1.2 |                   1.2 |     1.2 |
    |                  13. |                   13. |      13 |
    |                 -70. |                  -70. |     -70 |

さらに短いソリューションを探しています。

カスタムヘルパー関数を使用した短縮アプローチがあります。

create or replace function str(num in number) return varchar2
as
begin
    return rtrim(to_char(num, 'FM999999999999990.99'), '.');
end;

しかし、 カスタムpl/sql関数には大きなパフォーマンスオーバーヘッドがあります これは、大量のクエリには適していません。

28
Vadzim

きれいな(私にとって)形式で10進数を取得する唯一の方法は、とんでもないコードを必要とするようです。

私がこれまでに得た唯一の解決策:

CASE WHEN xy>0 and xy<1 then '0' || to_char(xy) else to_char(xy)

xyは10進数です。

xy             query result
0.8            0.8  --not sth like .80
10             10  --not sth like 10.00

このための実際のフォーマットオプションがある場合は、この質問に答えてください。

7
mkb

これは1未満の数値でのみ機能します。

select to_char(12.34, '0D99') from dual;
-- Result: #####

これは機能しません。

このようなことはできますが、これにより先頭に空白ができます:

select to_char(12.34, '999990D99') from dual;
-- Result: '     12,34'

最終的に、TRIMを追加して空白を削除することもできますが、適切な解決策とは思わないでしょう...

select trim(to_char(12.34, '999990D99')) from dual;
-- Result: 12,34

繰り返しますが、これは最大6桁の数字でのみ機能します。

編集:これをDCookieの提案に対するコメントとして追加したかったのですが、できません。

4
rawberto

To_charの制限を避けるためにこれを試してください:

SELECT 
regexp_replace(regexp_replace(n,'^-\'||s,'-0'||s),'^\'||s,'0'||s)
FROM (SELECT -0.89 n,RTrim(1/2,5) s FROM dual);
1
user6404490

すべての場合に機能するはずです:

SELECT regexp_replace(0.1234, '^(-?)([.,])', '\10\2') FROM dual
0
Joël