是不是我们的神Oracle对小数不加零(oracle中小数不带0)
是不是我们的神?Oracle对小数不加零
作为数据库领域的巨头之一,Oracle被广泛应用于各种企业级应用系统中。然而,在处理小数类型数据时,Oracle却展示出了让人摸不着头脑的行为:它不会自动在小数后面加上零。
在Oracle中,如果我们想要将一个小数保留两位小数并输出,通常会使用TO_CHAR函数,像这样:
“`sql
SELECT TO_CHAR(1.1, ‘9999999990.00’) FROM DUAL;
结果会输出1.10,因为我们的格式中指定了小数保留两位,并且不足两位时需要补零。然而,有意思的事情开始发生了。
当我们将格式中有小数点的部分去掉时,也就是让其只保留整数位,再运行如下代码:
```sqlSELECT TO_CHAR(1.1, '9999999990') FROM DUAL;
结果输出为1.1,而不是1.10,Oracle似乎忽略了格式中小数点后的零。
这个行为在实际项目中可能会照成不便和误解。如果对于小数的精度有一些特殊要求,此时我们需要使用ROUND函数,像这样:
“`sql
SELECT TO_CHAR(ROUND(1.1, 2), ‘9999999990’) FROM DUAL;
结果依旧是1.10,说明ROUND函数可以很好的保证精度不丢失。
到这里,我们还不能下定论,或许Oracle的这种行为是符合标准的。让我们看看SQL标准里对于数字类型输出格式的规定:
数字格式模型由一个区域符(在一些语言环境中),数码占位符和小数点占位符组成。语法如下(ABNF)
numeric_format_model::=
[ $ | € | £ | ¥ | ¤ | ]
bnumeric_format_elements.b ::=
[ G ] [ S ] [ B ] [ MI ] [ PR ] [ LR ] [ RN ] [ FM ]
[ TM ] [ TZH ] [ TZM ] [ TZR ] [ SIP ] [ W ]
[ E | EE | D | DD | MI | S | PR | L ] [ n ]
[ [(+|-)] mask_number_fmt ]
mask_number_fmt ::=
[ [CV] [BN] [Z] [9] [PR] [FM] [TH] * | X | A | MI | S | SQL | :
本地化数字格式可以包括字符如(例如$等)和数字格式元素,下面的表格定义了数字格式元素:
元素 名称 说明
G 组分隔符 千位分隔符
S 正数前缀 正数符号的前缀
B 正数后缀 正数符号的后缀
MI 负数前缀 负数符号的前缀
PR 正负前缀 正负符号的前缀
LR 货币本地化 本地化货币类型
RN 数字化字符串 的值
FM 格式化化 格式化的第一位
TM 文本前缀 文本符号的前缀
TZH 时区修饰符(小时) 显示时区小时数
TZM 时区修饰符(分) 显示时区分钟数
TZR 时区名称 显示本地时区名称
SIP 标准率 标准利率
W 大写文本 大写文本
E,EE,D,DD 指数 指数表示数字格式
MI 正数后缀 正数符号的后缀
S 正数前缀 正数符号的前缀
PR 正负前缀 正负符号的前缀
L 局部货币本地化 一些语言对局部货币符号的要求
n 数字 数字
mask_number_fmt ::=
[ [CV] [BN] [Z] [9] [PR] [FM] [TH] * | X | A | MI | S | SQL | :
逐行看,G、S、B、MI、S、PR、MI、S、PR这些元素都是可以影响到小数输出格式的。而略微让人意外的是,数字格式元素中完全没有零这个元素,这也许就是Oracle不加零的行为规定了吧。
不过,如果我们仍然想在Oracle中以0补齐小数位数,也并非毫无办法。我们可以使用LPAD函数,像这样:
```sqlSELECT LPAD(1.1, 4, '0') FROM DUAL;
结果输出为1.10,我们成功地用LPAD函数在小数后面补齐了零。
综上所述,虽然Oracle对小数不加零的行为看起来有些让人摸不着头脑,但在SQL标准里并非没有这样的规定,而ROUND函数、LPAD函数也可以帮我们解决这些问题。同样地,这也提示我们在编写各种应用程序时要谨慎处理小数的格式,以避免产生不必要的问题和混淆。