Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1415155
  • 博文数量: 247
  • 博客积分: 10147
  • 博客等级: 上将
  • 技术积分: 2776
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-24 15:18
文章分类

全部博文(247)

文章存档

2013年(11)

2012年(3)

2011年(20)

2010年(35)

2009年(91)

2008年(87)

我的朋友

分类: Oracle

2009-11-25 19:37:08

dump函数(number类型) 笔记

dump 函数能查看表中列在datafile存储内容。
Oracle的NUMBER类型最多由三个部分构成,这三个部分分别是最高位表示位、数据部分、符号位。其中负数包含符号位,正数不会包括符号位(10进制即102)。另外,数值0比较特殊,它只包含一个数值最高位表示位80(16进制),没有数据部分。

用法:DUMP(expr[,number_format[,start_position][,length]])

用法说明: dump(col_name,8|10|16|17) ,其中8|10|16|17 为number_format,分别为8进制,10进制(默认值),16进制,单字符。
 

The syntax is:

DUMP(expr[,return_fmt[,start_position[,length]]])

The argument return_fmt specifies the format of the return value and can have any of the following values:

  • 8 returns result in octal notation.
  • 10 returns result in decimal notation.
  • 16 returns result in hexadecimal notation.
  • 17 returns result as single characters.

By default, the return value contains no character set information. To retrieve the character set name of expr, specify any of the preceding format values, plus 1000. For example, a return_fmt of 1008 returns the result in octal, plus provides the character set name of expr.

The arguments start_position and length combine to determine which portion of the internal representation to return. The default is to return the entire internal representation in decimal notation.

If expr is null, then this function returns a null.



DUMP函数的输出格式类似:

类型 <[长度]>,符号/指数位 [数字1,数字2,数字3,......,数字20]

各位的含义如下:

1.类型: Number型,Type=2 (类型代码可以从Oracle的文档上查到,见结尾)

2.长度:指存储的字节数

3.符号/指数位

在存储上,Oracle对正数和负数分别进行存储转换:

正数:加1存储(为了避免Null),在实际算法中就是要减1,必须>128
负数:被101减,如果总长度小于21个字节,最后加一个102(是为了排序的需要),必须<128


指数位换算:

正数:指数=符号/指数位 - 193 (第一字节)
负数:指数=62 - 第一字节


4.从<数字1>开始是有效的数据位

从<数字1>开始是最高有效位,所存储的数值计算方法为:

将下面计算的结果加起来:

每个<数字位>乘以100^(指数-N) (N是有效位数的顺序位,第一个有效位的N=0)

===numbe类型例子====
例1:(区别正数和负数)
SQL> select dump(0) from dual;                                                  

DUMP(0)
--------------------------------
Typ=2 Len=1: 128
##
例1中可以看见,为什么>128断定为正数,而<128 断定为负数(10进制)

## 16进制分析正数和负数
SQL> select dump(0,16) from dual;                                               

DUMP(0,16)
------------------------------
Typ=2 Len=1: 80--------------------(只有高位)

1 row selected.

DUMP(0) 的结果是0x80,在前面已经提到,0只有高位表示位,没有数据位。由于0的特殊,既不属于正数,也不属于负数,因此使用高位表示位用80表示就足够了, 不会和其它数据冲突,Oracle出于节省空间的考虑将后面数据部分省掉了。但是为什么Oracle选择0x80表示0呢?我们知道正数和负数互为相反 数,每个正数都有一个对应的负数。因此如果我们要使用编码表示数值,则表示正数和负数的编码应该各占一半,这样才能保证使Oracle表示数据范围是合理的。而0x80的二进制编码是1000 0000,正好是一个字节编码最大值的一半,因此,Oracle选择0x80来表示0,是十分有道理的。


@@@@

例2:(正数)
SQL> select dump(1,10) from dual;                                               

DUMP(1,10)
------------------------------------
Typ=2 Len=2: 193,2
                       |   |
                    高位,数据部分


1 row selected.  

##
SQL> select dump(1) from dual;                                                                                                                                                   

DUMP(1)
------------------------------------
Typ=2 Len=2: 193,2

1 row selected.
##
例2中可以看见dump(1,10)和dump(1) 输出结果一样:Typ=2 Len=2: 193,2
类型是number,2字节,因为正数所以>128,因为正数所以存储时候都+1

<指数>:   193 - 193 = 0
<数字1>      2 - 1    = 1 *100^(0-0)
                             = 1

@@@@@@@@
例3:(正数指数变化)
SQL> select dump(99) from dual;                                                

DUMP(99)
----------------------------------------
Typ=2 Len=2: 193,100

1 row selected.


##

SQL> select dump(100) from dual;                                                

DUMP(100)
------------------------------------
Typ=2 Len=2: 194,2

1 row selected.

例3对比就知道,第一字节指数从193变化到194

@@@@@@@@@@@

例4:(负数)
SQL> select dump(-98) from dual;                                                

DUMP(-98)
------------------------------------------
Typ=2 Len=3: 62,3,102
                     |   |    |
                高位,数据部分,符号位
                        




1 row selected.
<指数>     62 - 62 = 0
<数字1> 101 -   3 = 98 *100^(0-0)
                          = 98

##
SQL> select dump(-99) from dual;                                                

DUMP(-99)
------------------------------------------
Typ=2 Len=3: 62,2,102

1 row selected.

<指数>     62 - 62 = 0
<数字1> 101 -   2 = 99 *100^(0-0)
                          = 99




###
SQL> select dump(-100) from dual;                                               

DUMP(-100)
----------------------------------------------
Typ=2 Len=3: 61,100,102

1 row selected

最后加102是目的:
实际存储中-98 为62,3   
               -99 为62,2     
               -100为61,100

得知-98>-99>-100

但是如果
SQL> select dump(-98.001) from dual;                                            

DUMP(-98.001)
--------------------------------------------------------
Typ=2 Len=5: 62,3,101,91,102

1 row selected.

通过这个得知 没有102:-98.001为 62,3,101,91  >-98 为62,3

                      有102:-98.001为 62,3,101,91,102
                                 -98     为   62,3,102


所以加102目的是排序的需要!


例5:(数字位算法)
SQL> select dump(7654321) from dual;                                            

DUMP(7654321)
------------------------------------------------------
Typ=2 Len=5: 196,8,66,44,22

1 row selected.

<指数>:   196 - 193 = 3
<数字1>    8  - 1    = 7 *100^(3-0) 7000000
<数字2>    66 - 1    = 65 *100^(3-1) 650000
<数字3>    44 - 1    = 43 *100^(3-2) 4300
<数字4>    22 - 1    = 21 *100^(3-3) 21

##
SQL> select dump(87654321) from dual;                                          

DUMP(87654321)
--------------------------------------------------------
Typ=2 Len=5: 196,88,66,44,22

1 row selected.



<指数>:   196 - 193 = 3
<数字1>    88  - 1    = 87 *100^(3-0) 87000000
<数字2>    66 - 1    = 65 *100^(3-1) 650000
<数字3>    44 - 1    = 43 *100^(3-2) 4300
<数字4>    22 - 1    = 21 *100^(3-3) 21




×××××××××××××××
类型代码(参考)
代码 数据类型 oracle 版本
1 varchar2   7
2 number    7
8 long    7
12 date    7
23 raw    7
24 long raw   7
69 rowid    7
96 char    7
112 clob    8
113 blob    8
114 bfile    8
180 timestamp   9i
181 timestamp with timezone  9i
182 interval year to month  9i
183 interval day to second  9i
208 urowid    8i
231 timestamp with local timezone 9i
 
 
****************************************************************
****************************************************************

Oracle在数据库内部通过相应的算法转换来进行数据存储,本文简单介绍Oracle的Number型数值存储及转换.

我们可以通过DUMP函数来转换数字的存储形式,一个简单的输出类似如下格式:

SQL> select dump(1) from dual;
DUMP(1)
------------------
Typ=2 Len=2: 193,2

DUMP函数的输出格式类似:

类型 <[长度]>,符号/指数位 [数字1,数字2,数字3,......,数字20]

各位的含义如下:

1.类型: Number型,Type=2 (类型代码可以从Oracle的文档上查到)

2.长度:指存储的字节数

3.符号/指数位

在存储上,Oracle对正数和负数分别进行存储转换:

正数:加1存储(为了避免Null)
负数:被101减,如果总长度小于21个字节,最后加一个102(是为了排序的需要)

指数位换算:

正数:指数=符号/指数位 - 193 (最高位为1是代表正数)
负数:指数=62 - 第一字节

4.从<数字1>开始是有效的数据位

从<数字1>开始是最高有效位,所存储的数值计算方法为:

将下面计算的结果加起来:

每个<数字位>乘以100^(指数-N) (N是有效位数的顺序位,第一个有效位的N=0)

5. 举例说明

SQL> select dump(123456.789) from dual;
DUMP(123456.789)
-------------------------------
Typ=2 Len=6: 195,13,35,57,79,91

<指数>:   195 - 193 = 2
<数字1>    13 - 1    = 12 *100^(2-0) 120000
<数字2>    35 - 1    = 34 *100^(2-1) 3400
<数字3>    57 - 1    = 56 *100^(2-2) 56
<数字4>    79 - 1    = 78 *100^(2-3) .78
<数字5>    91 - 1    = 90 *100^(2-4) .009
                            123456.789

SQL> select dump(-123456.789) from dual;
DUMP(-123456.789)
----------------------------------
Typ=2 Len=7: 60,89,67,45,23,11,102

<指数>     62 - 60 = 2(最高位是0,代表为负数)
<数字1> 101 - 89 = 12 *100^(2-0) 120000
<数字2> 101 - 67 = 34 *100^(2-1) 3400
<数字3> 101 - 45 = 56 *100^(2-2) 56
<数字4> 101 - 23 = 78 *100^(2-3) .78
<数字5> 101 - 11 = 90 *100^(2-4) .009
                               123456.789(-)

现在再考虑一下为什么在最后加102是为了排序的需要,-123456.789在数据库中实际存储为

60,89,67,45,23,11

而-123456.78901在数据库中实际存储为

60,89,67,45,23,11,91

可见,如果不在最后加上102,在排序时会出现-123456.789<-123456.78901的情况。

NUMBER数字类型为什么有2个字节的长度呢?

对于这个问题,我想我们应该知道,所有数据类型最终在计算机里都以二进制存储,实际上所谓的数据类型都是我们定义的.所以存储只由算法决定.

所以这个问题是不成立的.比如:

SQL> select dump(110) from dual;
DUMP(110)
---------------------
Typ=2 Len=3: 194,2,11
SQL> select dump(1100) from dual;
DUMP(1100)
-------------------
Typ=2 Len=2: 194,12

我们会看到,虽然1100>110,但是存储上1100却只占2字节,而110却占了3个字节.



阅读(2722) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~