Как преобразовать строку в число в Oracle, используя функцию TO_NUMBER с символом с фиксированной десятичной запятой?

#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. Как это отвечает на вопрос?