How to efficiently convert text to number in Oracle PL/SQL with non-default NLS_NUMERIC_CHARACTERS?

前端 未结 4 1171
眼角桃花
眼角桃花 2020-12-10 14:10

I\'m trying to find an efficient, generic way to convert from string to a number in PL/SQL, where the local setting for NLS_NUMERIC_CHARACTERS settings is inpredictable -- a

相关标签:
4条回答
  • 2020-12-10 14:35

    Sorry, I noticed later that your question was for the other way round. Nevertheless it's noteworthy that for the opposite direction there is an easy solution:

    A bit late, but today I noticed the special format masks 'TM9' and 'TME' which are described as "the text minimum number format model returns (in decimal output) the smallest number of characters possible." on https://docs.oracle.com/cloud/latest/db112/SQLRF/sql_elements004.htm#SQLRF00210.

    It seems as if TM9 was invented just to solve this particular problem:

    select to_char(1234.5678, 'TM9', 'NLS_NUMERIC_CHARACTERS=''.,''') from dual;
    

    The result is '1234.5678' with no leading or trailing blanks, and a decimal POINT despite my environ containing NLS_LANG=GERMAN_GERMANY.WE8MSWIN1252, which would normally cause a decimal COMMA.

    0 讨论(0)
  • select to_number(replace(:X,'.',to_char(0,'fmd'))) from dual;
    

    btw

    select to_number(replace('1.2345e-6','.',to_char(0,'fmd'))) from dual;
    

    and if you want more strict

    select to_number(translate(:X,to_char(0,'fmd')||'.','.'||to_char(0,'fmd'))) from dual;
    
    0 讨论(0)
  • 2020-12-10 14:59

    The following should work:

    SELECT to_number(:x, 
                     translate(:x, '012345678-+', '999999999SS'), 
                     'nls_numeric_characters=''.,''') 
      FROM dual;
    

    It will build the correct second argument 999.999999 with the efficient translate so you don't have to know how many digits there are beforehand. It will work with all supported Oracle number format (up to 62 significant digits apparently in 10.2.0.3).

    Interestingly, if you have a really big string the simple to_number(:x) will work whereas this method will fail.

    Edit: support for negative numbers thanks to sOliver.

    0 讨论(0)
  • 2020-12-10 15:01

    If you are doing a lot of work per session, an option may be to use ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,' at the beginning of your task.

    Of course, if lots of other code is executed in the same session, you may get funky results :-) However we are able to use this method in our data load procedures, since we have dedicated programs with their own connection pools for loading the data.

    0 讨论(0)
提交回复
热议问题