【问题标题】:NLS_NUMERIC_CHARACTERS setting for decimal十进制的 NLS_NUMERIC_CHARACTERS 设置
【发布时间】:2014-08-25 14:51:58
【问题描述】:

我在测试机器上设置了一个数据库,在生产机器上设置了第二个数据库。当我跑步时:

select to_number('100,12') from dual 

然后它在测试机器中给出错误。但是,此语句在生产机器上运行良好。

现在,当我检查 NLS_NUMERIC_CHARACTERS 时,我在两台机器上都看到了“,”(逗号)。还有其他地方我应该寻找小数设置吗?

干杯!

【问题讨论】:

    标签: oracle oracle11g oracle-sqldeveloper


    【解决方案1】:

    您可以通过查询nls_session_parameters查看您当前的会话设置:

    select value
    from nls_session_parameters
    where parameter = 'NLS_NUMERIC_CHARACTERS';
    
    VALUE                                  
    ----------------------------------------
    .,                                       
    

    这可能与数据库默认值不同,您可以在 nls_database_parameters 中看到。

    在此会话中您的查询错误:

    select to_number('100,12') from dual;
    
    Error report -
    SQL Error: ORA-01722: invalid number
    01722. 00000 -  "invalid number"
    

    我可以更改我的会话,直接使用alter session 或确保我的客户端配置方式导致设置字符串需要(例如,它可能继承自操作系统或 Java 语言环境):

    alter session set NLS_NUMERIC_CHARACTERS = ',.';
    select to_number('100,12') from dual;
    
    TO_NUMBER('100,12')
    -------------------
                 100,12 
    

    在 SQL Developer 中,您可以在 Tool->Preferences->Database->NLS 中设置您的首选值。

    但我也可以覆盖该会话设置作为查询的一部分,将可选的第三个 nlsparam 参数设置为to_number();虽然这使得可选的第二个 fmt 参数也是必需的,但您需要能够选择合适的格式:

    alter session set NLS_NUMERIC_CHARACTERS = '.,';
    select to_number('100,12', '99999D99', 'NLS_NUMERIC_CHARACTERS='',.''')
    from dual;
    
    TO_NUMBER('100,12','99999D99','NLS_NUMERIC_CHARACTERS='',.''')
    --------------------------------------------------------------
                                                            100.12 
    

    默认情况下,我的会话设置仍然显示结果,因此小数分隔符仍然是句点。

    【讨论】:

    • 谢谢。显然问题出在客户端软件上。我在一台机器上使用 oracle 开发人员,而在另一台机器上使用 PL/SQL 开发人员。
    • 是否可以在使用 to_number 时将“DEFAULT -1 ON CONVERSION ERROR”添加到您的最后一个选择查询中?在我的情况下,它会导致 Oracle 错误 ORA-43918。
    • @gouessej - 不是我写这个答案的时候 *8-) 而是yes, it is。也许您看到的是this
    • 感谢您的回答。当第一个参数是文字但不是列名时,您的示例有效。我刚刚尝试过使用 Oracle 19。提示没有帮助。
    • It does work with a column - 所以不确定你有什么不同。 (该提示可能仅适用于 12c;但在以后的版本中它应该可以在没有它的情况下工作)。使用minimal reproducible example 提出一个新问题可能值得。
    【解决方案2】:

    JaannaOracle SQL Developer 中的 session 参数取决于您的客户端计算机,而 NLS PL/SQL 上的参数来自服务器。

    例如,客户端计算机上的NLS_NUMERIC_CHARACTERS 可以是“,.”,而在服务器上它是“.,”。

    因此,当您从 PL/SQLOracle SQL Developer 运行脚本时,相同脚本的小数分隔符可能完全不同,除非您使用预期的 @ 更改会话987654322@ 在脚本中。

    轻松测试会话参数的一种方法是:

    select to_number(5/2) from dual;
    

    【讨论】:

    • 对不起,我不明白你的例子!为什么是 5/2 而不是 5,2 ?如果您的代码是正确的,我会误解一些东西:-)
    • OP 问题中没有提到 PL/SQL
    • @schlebe 所以你可以检查select语句的输出中的小数分隔符(点或逗号)是否正常
    【解决方案3】:

    要知道 SESSION 小数点分隔符,可以使用以下 SQL 命令:

    ALTER SESSION SET NLS_NUMERIC_CHARACTERS = ', ';
    
    select SUBSTR(value,1,1) as "SEPARATOR"
          ,'using NLS-PARAMETER' as "Explanation"
      from nls_session_parameters
      where parameter = 'NLS_NUMERIC_CHARACTERS'
    
    UNION ALL
    
    select SUBSTR(0.5,1,1) as "SEPARATOR" 
          ,'using NUMBER IMPLICIT CASTING' as "Explanation"
      from DUAL;
    

    第一个 SELECT 命令查找 NLS_SESSION_PARAMETERS 表中定义的 NLS 参数。小数分隔符是返回值的第一个字符。

    第二个 SELECT 命令使用(默认情况下)在会话级别定义的 NLS_NUMERIC_CHARACTERS 将 0.5 有理数隐式转换为字符串。

    两个命令返回相同的值。

    我已经在 PL/SQL 脚本中测试了相同的 SQL 命令,并且始终显示相同的值 COMMA 或 POINT。 PL/SQL 脚本中显示的小数分隔符与 SQL 中显示的相同。

    为了测试我所说的,我使用了以下 SQL 命令:

    ALTER SESSION SET NLS_NUMERIC_CHARACTERS = ', ';
    
    select 'DECIMAL-SEPARATOR on CLIENT: (' || TO_CHAR(.5,) || ')' from dual;
    
    DECLARE
        S VARCHAR2(10) := '?';
    BEGIN
    
        select .5 INTO S from dual;
    
        DBMS_OUTPUT.PUT_LINE('DECIMAL-SEPARATOR in PL/SQL: (' || S || ')');
    END;
    /
    

    知道小数分隔符的较短命令是:

    SELECT .5 FROM DUAL;
    

    如果小数点分隔符是 COMMA,则返回 0,5,如果小数点分隔符是 POINT,则返回 0.5

    【讨论】:

      【解决方案4】:

      最好的办法是,

      SELECT to_number(replace(:Str,',','')/100) --into num2 
      FROM dual;
      

      【讨论】:

      • 在问题中使用代码时,请将所有代码放入代码块中:通常,所有代码行缩进4个空格,或者在代码块周围加上3个反引号(```)。对于与非代码位于同一行的内联代码,请在代码的每一侧使用一个反引号 (`) 将代码括起来。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-22
      • 1970-01-01
      相关资源
      最近更新 更多