В Oracle при преобразовании числа с начальным нулем в символ почему исчезает лидирующее число? Является ли эта логика Oracle специфичной или специфичной для SQL?
Пример:
SELECT TO_CHAR(0.56) FROM DUAL;
/* Result = .56 */
В Oracle при преобразовании числа с начальным нулем в символ почему исчезает лидирующее число? Является ли эта логика Oracle специфичной или специфичной для SQL?
Пример:
SELECT TO_CHAR(0.56) FROM DUAL;
/* Result = .56 */
Это форматирование по умолчанию, предоставляемое 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:
Я искал способ форматирования чисел без начальных или конечных пробелов, точек, нулей (за исключением одного начального нуля для чисел меньше 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 имеют значительные издержки производительности, что не подходит для сложных запросов.
Кажется, что единственный способ получить десятичную форму в симпатичной (для меня) форме требует какого-то смешного кода.
Единственное решение, которое я получил до сих пор:
CASE WHEN xy>0 and xy<1 then '0' || to_char(xy) else to_char(xy)
xy
является decimial.
xy query result
0.8 0.8 --not sth like .80
10 10 --not sth like 10.00
ответьте на этот вопрос, если для этого есть реальная форма.
Это работает только для чисел меньше 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, но я не могу.
Попробуйте это, чтобы избежать ограничений 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);
Должно работать во всех случаях:
SELECT regexp_replace(0.1234, '^(-?)([.,])', '\10\2') FROM dual