当前位置:数据库 > Oracle >>

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

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的内部存储格式有关,不做过多的讨论。
[sql] 
SQL> create table t6(c1 number,c2 number(*,1),c3 number(9),c4 number(9,2),c5 number(9,1),c6 number(6),c7 number(7,-2));  
  
表已创建。  
  
SQL> insert into t6 values(7456123.89,7456123.89,7456123.89,7456123.89,7456123.89,7456123.89,7456123.89);  
insert into t6 values(7456123.89,7456123.89,7456123.89,7456123.89,7456123.89,7456123.89,7456123.89)  
                                                                             *  
第 1 行出现错误:  
ORA-01438: 值大于为此列指定的允许精度  
  
  
SQL> insert into t6 values(7456123.89,7456123.89,7456123.89,7456123.89,7456123.89,0,7456123.89);  
  
已创建 1 行。  
  
SQL> commit;  
[sql] 
SQL> select * from t6;  
  
      C1           C2       C3       C4       C5       C6       C7  
------------ ------------ ------------ ------------ ------------ ------------ ------------  
  7456123.89    7456123.9      7456124   7456123.89    7456123.9        0      7456100  
number存储结构
        number数据类型的存储结构,可以通过dump函数来展现,在探究number存储结构之前,让我们先来看一下dump函数的使用方法。
        DUMP函数的输出格式类似:
类型 <[长度]>,符号/指数位 [数字1,数字2,数字3,……,数字20]
        其中各参数的含义如下:
·类型指字段数据类型,Number型,Type=2(类型代码可以从Oracle的文档上查到);
·长度指存储的字节数;
·符号/指数位用于代表数字的正负及指数值;
·数据存储。
 
        oracle采用21个字节存储number,第一个字节为头信息,随后20个字节存储有效数字。
         头信息        数据域1      数据域2   .............. 数据域n (n<=20)
         XXXXXXXXXXXXXXXX XXXXXXXX ............XXXXXXXX
         |  |                   |-一个字节存储2个十进制数字,可以存储0-99,因为0在c语言中作为特殊字符,因此用1-100来存储0-99,即在原值上加1。在数据域不存储正负符号,为了
         |  |                   |-排序的方便,对于负数,我们用101-2来存储0-99(为什么不用100-1,请高手指教),在负数的最后会添加一个值为102的字节,这是为了避免排序错误
         |  |-数据指数范围标识位,当正数时,该数值与64做差(x-64),其结果为指数,当负数时,63与该数值做差(63-x),其结果为指数。在oracle中0X80,代表0,因此对于
         |  |-正数,其指数范围为-63~0(小数) 1~63(非小数);对于负数,指数范围为63~1(非小数),0~-64(小数)
         |-符号信息位,1代表正数,0代表负数
          查询是,对于存储在数据域的数据,oracle会将每个字节转换为十进制,然后拼接各个字节。如果指数域的值为正数n,那么会将小数点定位在第n个字节的后面,如果为0,则小数点在第一个字节的前面,如果为负数,则小数点在第一个字节向前推进n个字节。
 
        下面,我们通过实例来看一下上面的说法正不正确:
[sql] 
desc tab1  
名称 空值 类型              
-- -- -------------   
C1    NUMBER          
C2    VARCHAR2(300)   
 
 
 
 
如果负数的精度很 大,102比较位可能会被舍弃,因此此时102已经起不到任何作用了。
       
[sql] 
SQL> insert into tab1 values(-111111111111111111111111111111111111111111111111111111111111);  
  
已创建 1 行。  
  
SQL> select dump(c1) from tab1;  
  
DUMP(C1)  
--------------------------------------------------  
Typ=2 Len=2: 193,2  
Typ=2 Len=3: 62,100,102  
Typ=2 Len=1: 128  
Typ=2 Len=6: 197,2,24,46,68,90 &
Oracle
MySQL
Access
SQLServer
DB2
Excel
SQLite
SYBASE
Postgres
如果你遇到数据库难题:
请访问www.zzzyk.com 试试
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,