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

5q4ezhmt  于 2022-12-03  发布在  Oracle
关注(0)|答案(8)|浏览(257)

在Oracle中,当将一个带有前导零的数字转换为字符时,为什么前导数字会消失?这是Oracle特有的逻辑,还是SQL特有的逻辑?
示例:

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

ac1kyiln1#

我一直在寻找一种方法来格式化数字,而不带前导或尾随spaces、句点、零(除了应该存在的小于1的数字的一个前导零)。
令人沮丧的是,在Oracle中无法轻松实现这种最常见的格式化。
即使是汤姆·凯特也只建议了这样一种冗长复杂的变通办法:

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;

但是custom pl/sql functions have significant performace overhead不适合于繁重的查询。

inb24sb2

inb24sb22#

这是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(数字,格式)

lc8prwob

lc8prwob3#

似乎唯一的方法来获得十进制在一个漂亮的(对我来说)形式需要一些荒谬的代码。
到目前为止我得到的唯一解决办法是:

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
dxpyg8gm

dxpyg8gm4#

这只对小于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建议的评论,但我不能。

31moq8wy

31moq8wy5#

尝试以下操作以避免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);
lkaoscv7

lkaoscv76#

应在所有情况下工作:

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

ztyzrc3y7#

如果数字类似,请尝试以下格式
例1假设像10.1这样数字,如果应用下面的格式,它将是10.10
例2假设数字像.02,如果应用下面的格式,它将是0.02
例3假设像0.2这样数字,如果应用下面的格式,它将是0.20
to_char(舍入(到_数字(列名)/10000000,2),'999999999990 D99')作为列名

xzlaal3s

xzlaal3s8#

如果您所在的国家/地区支持逗号表示十进制,请使用以下格式:

SELECT regexp_replace(
            regexp_replace(to_char(YOUR_NUMBER), '^,', '0,'), -- Positives
            '^-,', '-0,') -- Negatives

否则,如果您所在的国家/地区支持表示小数,请使用以下代码:

SELECT regexp_replace(
            regexp_replace(to_char(YOUR_NUMBER), '^.', '0.'), -- Positives
            '^-.', '-0.') -- Negatives

相关问题