读书人

ORACLE数值类型详解-NUMBER、FLOAT、B

发布时间: 2013-10-25 14:36:53 作者: rapoo

ORACLE数值类型详解--NUMBER、FLOAT、BINARY_FLOAT、BINARY_DOUBLE、BINARY_INTEGER

在9i之前,ORACLE为我们提供了Number数值类型,在10g中,ORACLE又引入了BINARY_FLOAT和BINARY_DOUBLE数据类型。除此之外,还有integer,smallint等数据类型,但这些类型的底层实现依然是NUMBER、BINARY_FLOAT、BINARY_DOUBLE。因此,我们可以认为ORACLE总共为我们提供了三种存储数值的数据类型:NUMBER、BINARY_FLOAT、BINARY_DOUBLE。通过这三种数值类型,可以存储正值,负值,0,无穷大和NAN(not a number)。

NUMBER

number类型在oracle中会占用0~22个字节的存储空间,是一种变长数据类型,采用oracle内部算法,是一种软数据类型,因此具有较好的数据精确度,通用性和可移植性较强,但是其运算效率相对一浮点类型(硬件运算)偏低。在0~22个字节的存储空间中,一个字节用于存储数据长度,21个字节用于存储数据(其中一个字节存储与符号和指数相关的内容,20个字节用于存储数据)。

number存储数据的范围如下:

正数:1 x 10-130 to 9.99...9 x 10125 ,数据精度为38个有效数字

负数:-1 x 10-130 to 9.99...99 x 10125 ,数据精度为38个有效数字

零:0

无穷大:仅仅只可以从oracle 5中导入

number有效数字

可以通过如下格式来指定:COLUMN_NAME number(precision ,scale),其中precision指number可以存储的最大数字长度(不包括左右两边的0),scale指在小数点右边的最大数字长度(包括左侧0)。如果我们指定了p和s,可以按照如下算法来判读数据是否有效:如果s>=0,首先我们从小数点从左向右数s个数字,如果在此之右,仍然有数据,则将其截断,然后我们在当前位置再向左侧数p个数字,如果在此之左仍有非零数字,则数字不合法,否则数据合法;如果s<0,首先我们从小数点从右向做数|s|个数字,并截断其右侧数据,然后我们在当前位置再向左侧数p个数字,如果在此之左仍有非零数字,则数字不合法,否则数据合法。

如果我们没有指定phes如:column_name number,则数字按照输入格式存储;如果我们指定了p,但是没有指定s,则s默认为0,如column_name number(p);如果我们指定了s但是没有指定p,则p默认为38,如column_name number(*,s)。

p的取值范围为1-38,在官方文档中有这样一段话:

Oracle guarantees the portability of numbers with precision of up to 20 base-100 digits, which is equivalent to 39 or 40 decimal digits depending on the position of the decimal point.由于在内部采用20个字节存储数据,每个字节存储2位数字,因此最多可以存放40个数字,及文档中谈及的40,但是如果小数点左侧的数字数量为奇数,则左侧补一位0,那么这是有效数字就最大为39。在语法上,oracle规定precision为38,可能是为了稳妥或者其他的原因。

s的取值范围为-84~127,这也是与number的内部存储格式有关,不做过多的讨论。


如果负数的精度很 大,102比较位可能会被舍弃,因此此时102已经起不到任何作用了。

SQL> create table tab1(id number,c1 binary_float,c2 binary_double);表已创建。SQL> insert into tab1 values(1,1,1);已创建 1 行。SQL> insert into tab1 values(2,nan,nan);insert into tab1 values(2,nan,nan)                              *第 1 行出现错误:ORA-00984: 列在此处不允许SQL> insert into tab1 values(2,binary_float_nan,binary_double_nan);已创建 1 行。SQL> insert into tab1 values(3,binary_float_infinity,binary_double_infinity);已创建 1 行。SQL> insert into tab1 values(4,-binary_float_infinity,-binary_double_infinity);已创建 1 行。SQL> commit;提交完成。SQL> select * from tab1;    ID       C1  C2------ ---------- ----------     1 1.0E+000   1.0E+000     2      Nan Nan     3      Inf Inf     4     -Inf-InfSQL> select * from tab1 order by c1;    ID       C1  C2------ ---------- ----------     4     -Inf-Inf     1 1.0E+000   1.0E+000     3      Inf Inf     2      Nan NanSQL> select * from tab1 where c1 is infinite;    ID       C1  C2------ ---------- ----------     3      Inf Inf     4     -Inf-InfSQL> select * from tab1 where c1 is nan;    ID       C1  C2------ ---------- ----------     2      Nan NanSQL> select * from tab1 where c1 = binary_float_infinity;    ID       C1  C2------ ---------- ----------     3      Inf InfSQL> select * from tab1 where c1 != binary_float_infinity;    ID       C1  C2------ ---------- ----------     1 1.0E+000   1.0E+000     2      Nan Nan     4     -Inf-InfSQL> select * from tab1 where c1 = (select c1 from tab1 where id =2);    ID       C1  C2------ ---------- ----------     2      Nan NanSQL> select * from tab1 where c1 = nan;select * from tab1 where c1 = nan                              *第 1 行出现错误:ORA-00904: "NAN": 标识符无效SQL> select * from tab1 where c1 = binary_float_nan;    ID       C1  C2------ ---------- ----------     2      Nan NanSQL> select * from tab1 where c1 = (select c1 from tab1 where id =3);    ID       C1  C2------ ---------- ----------     3      Inf InfSQL> 
优先级:在数据转换时,优先转换为高级别的数据类型date type > binary_double > binary_float > number > char
1楼Etoak_james昨天 16:28
不错 帮顶了。QQ群294881724 java高性能与sql优化讨论

读书人网 >其他数据库

热点推荐