oracle - 考虑到在数据库服务器上定义的NLS_NUMERIC_CHARACTERS,如何使用正确的TO_NUMBER()Oracle函数?

标签 oracle function internationalization nls

今天,我发现Oracle NLS_NUMERIC_CHARACTERS的定义不明确!

确实,从一开始,我就认为NLS_NUMERIC_CHARACTERS仅用于定义十进制数字的显示方式。

但实际上,NLS_NUMERIC_CHARACTERS函数中还隐式使用了TO_NUMBER()来定义要转换的STRING编号的格式。

我的问题是我是欧洲人,对我来说,十进制分隔符实际上是逗号(,),而不是点(.)。

当我显示一个数字时,我的偏好是使用逗号显示它。因此,NLS_NUMERIC_CHARACTERS设置为',.',其中第一个字符定义数字分隔符。

到目前为止,我对此没有任何问题:-)

我的问题是,包含数字的所有String表字段的值都使用POINT字符作为小数点分隔符。

当我将任何表示数字的字符串值转换时,可以使用TO_NUMBER Oracle函数,如下所示

select TO_NUMBER(VALUE) from TB_PARAMETER;

如果小数点分隔符为POINT(NLS_NUMERIC_CHARACTERS = '.,'),则此方法效果很好,但如果小数点分隔符为COMMA(NLS_NUMERIC_CHARACTERS = ',.'),则此方法停止工作。

我知道我可以像这样在NLS_NUMERIC_CHARACTERS函数中指定TO_NUMBER()
select TO_NUMBER(VALUE
                ,'999999999D999999999'
                ,'NLS_NUMERIC_CHARACTERS = ''.,'''
                )
  from TB_PARAMETER;

但这对我来说很冗长!

是否有执行相同功能的Oracle函数?

例:
select CAST_NUMBER(VALUE) from TB_PARAMETER;

从个人角度来说,我认为Oracle TO_NUMBER()函数使用NLS_NUMERIC_CHARACTERS session 的参数来定义要转换的十进制字符串格式的事实是错误

实际上,在数据库中,字符串中使用的十进制分隔符始终是固定的。它是逗号或一点,但绝不是逗号,一次是点。

如果我的分析是正确的,则TO_NUMBER()函数必须始终使用一个固定值,即POINT或COMMA(在所有情况下均不与NLS_NUMERIC_CHARACTERS对应),因为此参数具有 session 范围,并且由Oracle客户端应用程序定义。

在简历中,当您在Oracle View 中使用TO_NUMBER()函数而不指定任何NLS_NUMERIC_CHARACTERS时,您的 View 将正确运行,直到在具有另一个NLS_NUMERIC_CHARACTERS值的 session 中执行该 View 为止!

当您尝试使用Oracle TO_DATE()函数转换保存为字符串的DATE值时,肯定存在同样的事情!

为什么模棱两可!

为了回答评论中的一些问题,我在以下段落中添加了我的详细解释。

由于NLS_NUMERIC_CHARACTERS具有两个不同的角色或目标,因此在 session 级别或系统级别更改NLS_NUMERIC_CHARACTERS并不总是可能的。
  • 固定显示小数点的小数点分隔符
  • 固定用于在TO_NUMBER()中转换字符串的小数点分隔符
    函数

  • 示例:假设您将创建一个显示十进制数字并使用TO_NUMBER()进行计算的 View 。

    如果保存在数据库中的小数点分隔符是POINT,并且有必要使用COMMA作为小数点分隔符显示小数点,则可以更改NLS_NUMERIC_CHARACTERS以将小数点分隔符定义为POINT。 Oracle TO_NUMBER()函数将正确运行,但屏幕上显示的小数将以POINT作为小数分隔符显示!

    这就是为什么我说NLS_NUMERIC_CHARACTERS不明确。

    在简历中,在数据库系统中NLS_NUMERIC_CHARACTERS可以为“。”或“。”。 AND,可以使用固定的格式将十进制数保存在Oracle表中(例如:十进制分隔符为POINT),使用TO_NUMBER()而不指定正确的NLS_NUMERIC_CHARACTERS是不安全的。

    Oracle错误(或者您可能会误解)是定义了具有2个不同角色的参数(NLS_NUMERIC_CHARACTERS)!

    最佳答案

    从我的角度来看,最好的选择是将数字保留在NUMBER数据类型列中。您如何将TO_NUMBER应用于value = '32.5rzg'

    除此之外,我假设您已经发现(应用NLS_NUMERIC_CHARACTERS)是可以做的,除了使用REPLACE并将所有点转换为整个字符串值中的逗号之外。

    关于oracle - 考虑到在数据库服务器上定义的NLS_NUMERIC_CHARACTERS,如何使用正确的TO_NUMBER()Oracle函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51962063/

    相关文章:

    sql - 甲骨文。将 varchar 值 "40.00"转换为数字

    performance - 让 Oracle 9i 使用索引

    r - 如何在 ggplot 函数中使用以数字开头的列名

    c++ - 基于不同字段的对象 vector 的排序函数

    java - 无法使用 dropjava 命令从 Oracle 数据库中删除 jar

    java - JDBC setNull() 与 Oracle "is null"产生不同的结果

    c++ - 函数类在运行时接受来自容器的可变数量的参数

    javascript - Intl 未定义 firefox

    java - I18n - 数据位于一种语言环境中,ui 位于另一种语言环境中,我应使用哪种语言环境进行排序?

    django - 我如何知道 Django 忽略 Accept-Language header 的原因?