今天,我发现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
会话的参数来定义要转换的十进制字符串格式的事实是 bug 。
实际上,在数据库中,字符串中使用的小数点分隔符始终是固定的。它是逗号或一点,但绝不是逗号,一次是点。
如果我的分析是正确的,则TO_NUMBER()
函数必须始终使用一个固定值,即POINT或COMMA(在所有情况下都不与NLS_NUMERIC_CHARACTERS对应),因为此参数具有会话范围并已定义通过Oracle客户端应用程序。
在简历中,当您在Oracle视图中使用TO_NUMBER()
函数而不指定任何NLS_NUMERIC_CHARACTERS
时,您的视图将保持正确性,直到在具有另一个不同的NLS_NUMERIC_CHARACTERS
的会话中执行该视图为止值!
当您尝试使用Oracle TO_DATE()
函数转换保存为字符串的DATE值时,肯定存在同样的事情!
为什么模棱两可!
为回答评论中的一些问题,我在以下段落中添加了我的详细解释。
由于在NLS_NUMERIC_CHARACTERS具有两个不同的角色或目标,因此在会话级别或系统级别更改NLS_NUMERIC_CHARACTERS并不总是可能的。
示例:假设您将创建一个显示十进制数字并使用TO_NUMBER()进行计算的视图。
如果保存在数据库中的小数点分隔符为POINT,并且有必要使用COMMA作为小数点分隔符显示小数点,则可以更改NLS_NUMERIC_CHARACTERS以将小数点分隔符定义为POINT。 Oracle TO_NUMBER()函数将正确运行,但屏幕上显示的十进制数字将以POINT作为十进制分隔符显示!
这就是为什么我说NLS_NUMERIC_CHARACTERS不明确。
在简历中,在数据库系统中NLS_NUMERIC_CHARACTERS可以为“。”或“。”。 AND,可以使用固定格式(例如:小数点分隔符为POINT)将十进制数保存在Oracle表中,使用TO_NUMBER()而不指定正确的NLS_NUMERIC_CHARACTERS是不安全的。
Oracle错误(或者您可能会误解)是定义了具有两个不同角色的参数(NLS_NUMERIC_CHARACTERS)!
答案 0 :(得分:3)
从我的角度来看,最好的选择是将数字保留在for i in range(1,20):
a = a.replace('TABLESPACE "D'+str(i).zfill(2)+'"','TABLESPACE COPY_TBS')
数据类型列中。您如何将NUMBER
应用于TO_NUMBER
?
除此之外,我想您已经发现(应用value = '32.5rzg'
)是可以做的,除了使用NLS_NUMERIC_CHARACTERS
并在所有字符串值中将所有点都转换为逗号之外。
答案 1 :(得分:1)
有关信息,我创建了关注函数
CREATE FUNCTION TO_X_NUMBER(sNumber IN VARCHAR2)
RETURN NUMBER as
BEGIN
RETURN TO_NUMBER
(sNumber
,'99999999999999999999D99999999999999999999'
,'NLS_NUMERIC_CHARACTERS=''.,''');
END TO_X_NUMBER;
和同义词
CREATE PUBLIC SYNONYM TO_X_NUMBER FOR GWHDBA.TO_X_NUMBER;
GRANT EXECUTE ON TO_X_NUMBER TO PUBLIC;
我现在可以从另一个架构中使用它,如以下示例所示:
SELECT TO_X_NUMBER(PARAM_VALUE) as STANDARD_DEVIATION
FROM TB_PARAMETER
WHERE PARAM_NAME = 'STANDARD_DEVIATION';