今天,我发现Oracle NLS_NUMERIC_CHARACTERS
的定义含糊不清!
实际上,从一开始,我就认为NLS_NUMERIC_CHARACTERS
仅用于定义如何显示十进制数。
但实际上,NLS_NUMERIC_CHARACTERS
也隐含在TO_NUMBER()
函数中,用于定义要转换的STRING数的格式。
我的问题是,我是欧洲人,对我来说,十进制分隔符实际上是逗号(,),而不是点(.)。
当我显示一个数字时,我的首选项是使用逗号显示它。因此,NLS_NUMERIC_CHARACTERS
被设置为',.'
,其中第一个字符定义数字分隔符。
直到现在,我对此没有意见:-)
我的问题是,所有String
表的字段值包含一个数字是使用点字符作为小数点分隔符。
当我转换任何表示数字的字符串值时,我可以像这样使用TO_NUMBER Oracle函数
select TO_NUMBER(VALUE) from TB_PARAMETER;
如果小数点分隔符是一个点(NLS_NUMERIC_CHARACTERS = '.,'
),则此操作很有效,但如果小数点分隔符是一个逗号(NLS_NUMERIC_CHARACTERS = ',.'
),则此操作停止。
我知道可以在TO_NUMBER()
函数中指定NLS_NUMERIC_CHARACTERS
,如下所示
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
会话的参数来定义要转换的十进制字符串的格式是一个bug。
事实上,在数据库中,字符串中使用的十进制分隔符总是固定的,它是逗号或点,但从来没有,一次是逗号,另一次是点。
如果我的分析是正确的,TO_NUMBER()
函数必须始终使用一个固定值,该值是一个不对应于(在所有情况下)NLS_NUMERIC_CHARACTERS的POINT或COMMA,因为此参数具有会话作用域,并由Oracle客户端应用程序定义。
在简历中,当您使用TO_NUMBER()
函数而未在Oracle视图中指定任何NLS_NUMERIC_CHARACTERS
时,您的视图将正常工作,直到在具有另一个不同NLS_NUMERIC_CHARACTERS
值的会话中执行它!
当您尝试使用Oracle TO_DATE()
函数转换保存为字符串的DATE值时,同样的事情肯定存在!
- 为何如此暧昧**
为了回答评论中的一些问题,我在下面的段落中添加了我的详细解释。
在会话级别或系统级别更改NLS_NUMERIC_CHARACTERS并不总是可行的,因为NLS_NUMERIC_CHARACTERS具有两个不同的角色或目标。
1.修复十进制数的十进制分隔符显示
1.修复用于转换TO_NUMBER()函数中字符串的十进制分隔符
示例:假设您将创建一个视图,该视图将显示十进制数,并使用TO_NUMBER()进行一些计算。
如果数据库中保存的小数点分隔符为POINT,并且需要使用COMMA作为小数点分隔符来显示小数,则可以更改NLS_NUMERIC_CHARACTERS,将小数点分隔符定义为POINT。Oracle TO_NUMBER()函数将正常工作,但屏幕上显示的小数将使用POINT作为小数点分隔符来显示!
这就是为什么我说NLS_NUMERIC_CHARACTERS是不明确的。
在恢复中,在NLS_NUMERIC_CHARACTERS可以是.""或.""的数据库系统中,可以使用固定格式将十进制数保存在Oracle表中(例如:十进制分隔符为POINT),则在未指定正确的NLS_NUMERIC_CHARACTERS的情况下使用TO_NUMBER()是不安全的。
Oracle错误(或者误解,如果您愿意的话)是定义了一个具有两个不同角色的参数(NLS_NUMERIC_CHARACTERS)!
3条答案
按热度按时间m1m5dgzv1#
作为参考,我创建了以下函数
和同义词
现在我可以从另一个模式中使用它,如下例所示:
pengsaosao2#
从我的Angular 来看,最好的选择是在
NUMBER
数据类型列中保留数字,那么如何将TO_NUMBER
应用到value = '32.5rzg'
呢?除此之外,我假设您已经发现(应用
NLS_NUMERIC_CHARACTERS
)的就是您可以做的,除了使用REPLACE
并将所有字符串值中的点转换为逗号。soat7uwm3#
无论客户端NLS设置和输入字符串如何,始终执行正确操作的函数,
https://dbfiddle.uk/dim1wC2W