Oracle - почему ведущий ноль числа исчезает при преобразовании его в TO_CHAR - PullRequest
34 голосов
/ 14 июля 2011

В Oracle при преобразовании числа с начальным нулем в символ почему исчезает начальное число?Эта логика Oracle специфична или специфична для SQL?

Пример:

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

Ответы [ 5 ]

30 голосов
/ 14 июля 2011

Это форматирование по умолчанию, предоставляемое 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 (число, формат )

27 голосов
/ 14 января 2015

Я искал способ форматирования чисел без начального или конечного числа пробелы , точки, нули (кроме одного начального нуля для чисел меньше 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;

Но пользовательские функции pl / sql имеют значительные накладные расходы производительности , что не подходит для тяжелыхзапросы.

7 голосов
/ 22 октября 2014

Похоже, что единственный способ получить десятичную дробь в красивой (для меня) форме требует некоторого смешного кода.

Единственное решение, которое я получил до сих пор:

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

, пожалуйста, ответьте на этот вопрос, если для этого есть реальный формат.

4 голосов
/ 21 мая 2014

Это работает только для чисел меньше 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, но не могу.

1 голос
/ 31 мая 2016

Попробуйте, чтобы избежать ограничений 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...