Я пытаюсь найти эффективный, общий способ преобразования из строки в число в PL/SQL, где локальная настройка для параметров NLS_NUMERIC_CHARACTERS непредсказуема - и, предпочтительнее, я ее не коснусь. Формат ввода - это стандарт программирования "123.456789", но с неизвестным числом цифр на каждой стороне десятичной точки.
select to_number('123.456789') from dual;
-- only works if nls_numeric_characters is '.,'
select to_number('123.456789', '99999.9999999999') from dual;
-- only works if the number of digits in the format is large enough
-- but I don't want to guess...
to_number
принимает третий параметр, но в этом случае вы также должны указать второй параметр, и нет спецификации формата для "по умолчанию"...
select to_number('123.456789', null, 'nls_numeric_characters=''.,''') from dual;
-- returns null
select to_number('123.456789', '99999D9999999999', 'nls_numeric_characters=''.,''') from dual;
-- "works" with the same caveat as (2), so it rather pointless...
Существует другой способ использования PL/SQL:
CREATE OR REPLACE
FUNCTION STRING2NUMBER (p_string varchar2) RETURN NUMBER
IS
v_decimal char;
BEGIN
SELECT substr(VALUE, 1, 1)
INTO v_decimal
FROM NLS_SESSION_PARAMETERS
WHERE PARAMETER = 'NLS_NUMERIC_CHARACTERS';
return to_number(replace(p_string, '.', v_decimal));
END;
/
select string2number('123.456789') from dual;
который делает именно то, что я хочу, но он не кажется эффективным, если вы делаете это много раз в запросе. Вы не можете кэшировать значение v_decimal (выборка один раз и сохранение в переменной пакета), потому что он не знает, измените ли вы значение сеанса для NLS_NUMERIC_CHARACTERS, а затем снова сломаетесь.
Я что-то пропускаю? Или я слишком беспокоюсь, и Oracle делает это намного эффективнее, чем я бы дал ему кредит?