Oracle - 为什么转换为TO_CHAR时数字的前导零消失

时间:2011-07-14 15:17:19

标签: sql oracle oracle10g

在Oracle中,将带前导零的数字转换为字符时,为什么前导数字会消失?这个逻辑是Oracle特定的,还是特定于SQL的?

示例:

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

7 个答案:

答案 0 :(得分:31)

这是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(号码,format

答案 1 :(得分:25)

我一直在寻找一种格式化数字的方法,不带前导或尾随spaces,句点,零(除了一个前导零,小于1的数字应该存在)。

令人沮丧的是,这种最常见的格式化在Oracle中无法轻松实现。

即使Tom Kyte only suggested long complicated workaround也是这样:

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

但我能找到更短的解决方案,只提到一次价值:

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

works as expected代表所有可能的值:

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;

custom pl/sql functions have significant performace overhead不适合重度查询。

答案 2 :(得分:6)

似乎在漂亮(对我来说)形式中获取小数的唯一方法需要一些荒谬的代码。

我到目前为止唯一的解决方案:

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

xy是一个十分之一。

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

如果有真实的格式选项,请回答此问题。

答案 3 :(得分:4)

仅适用于小于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 :(得分:1)

尝试这样做以避免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);

答案 5 :(得分:0)

在所有情况下均应起作用:

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

答案 6 :(得分:0)

在以下格式下尝试数字是否为

ex 1假设数字如10.1,如果采用以下格式,它将为10.10

ex 2假设数字如.02,如果应用以下格式,它将为0.02

ex 3假设数字为0.2,如果采用以下格式,则为0.20

to_char(舍入(to_number(列名)/ 10000000,2),'999999999990D99')作为列名