#oracle #plsql #oracle10g #number-formatting
#Oracle #plsql #oracle10g #форматирование чисел
Вопрос:
Мне нужно преобразовать в процедуре из string
в decimal
с фиксированным десятичным разделителем .
независимо от настроек языка. Далее, я знаю, что десятичное число ограничено только 6 десятичными знаками после .
и нет ограничений на количество цифр перед .
. Используя документацию Oracle и ее примеры для форматирования строк, у меня теперь есть только это решение:
v_number := TO_NUMBER(v_string, '9999999999999999999999999999999999D999999', 'NLS_NUMERIC_CHARACTERS = ''. ''');
Количество 9
символов перед D
— максимально допустимое число. Я нахожу этот формат строки довольно ужасным. Есть ли какой-либо лучший формат строки для этого общего преобразования или какой-либо способ опустить второй параметр функции? В общем, мне просто нужно передать в функцию параметр NLS, чтобы сообщить ему, что я просто хочу преобразовать с десятичным разделителем .
, но второй параметр также является обязательным в этом случае.
Комментарии:
1. Если число в строковой форме всегда похоже на ‘9999.99999’, почему бы вам просто не использовать TO_NUMBER()? Вы хотите установить ограничение на наличие 6 цифр после запятой?
2. @cybernate:
to_number(:X)
проанализирует X в настройках NLS сеанса, который может иметь другой числовой разделитель, чем «.»
Ответ №1:
Вы не можете вызвать to_number
функцию с третьим параметром, а не со вторым. Я бы предложил поместить «уродливую» строку формата в константу пакета и забыть об этом.
Вы также могли бы использовать dbms_session.set_nls
для изменения настроек NLS и иметь возможность использовать to_number
без аргументов.
Комментарии:
1. 1 … или, используя ту же линию мышления, вы можете создать свою собственную (упакованную) функцию «our_to_number» и полностью скрыть детали реализации.
2. Вероятно, наиболее понятное решение. Спасибо, что убедил меня, что я на правильном пути.
Ответ №2:
Обрабатывает как запятую, так и точку.
FUNCTION to_number2(p_num_str VARCHAR2) RETURN NUMBER AS
BEGIN
RETURN TO_NUMBER(REPLACE(p_num_str, ',', '.'), '999999999999D999999999999', 'NLS_NUMERIC_CHARACTERS=''.,''');
END;
Ответ №3:
CREATE OR REPLACE FUNCTION IS_NUMBER(P_VAR IN VARCHAR2)
RETURN NUMBER
IS
P_NUMBER NUMBER := 0;
RIG VARCHAR2(10) := '';
FORMAT VARCHAR2(100) := '999999999999D999999999999';
RES VARCHAR2(100) := '';
BEGIN
SELECT VALUE INTO RIG
FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER = 'NLS_NUMERIC_CHARACTERS';
IF SUBSTR(RIG,1,1) = '.' THEN
RES := REPLACE(P_VAR,',','.');
ELSE
RES := REPLACE(P_VAR,'.',',');
END IF;
P_NUMBER := TO_NUMBER(RES,FORMAT,'NLS_NUMERIC_CHARACTERS='''||RIG||'''');
P_NUMBER := ROUND(P_NUMBER,5); --FIVE DIGITS AFTER DECIMAL POINT IS ENOUGH
RETURN P_NUMBER;
EXCEPTION
WHEN OTHERS THEN RETURN -1;
END;
Комментарии:
1. Не могли бы вы написать свой комментарий на английском, а не на русском?
2. ПЯТЬ ЗНАКОВ ПОСЛЕ ЗАПЯТОЙ ДОСТАТОЧНО = Five decimals are enough.
Ответ №4:
select to_number(' 12.5 ') to_number(' 12 ') from dual;
Комментарии:
1. Как это отвечает на вопрос?