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个字节.