这篇是关于ORALCE对NUMBER类型存储方式的探析, 以及试图对设计者的初始意图进行解释.
最近往上看了很多对ORACLE怎样进行数据存储进行描述的, 感觉都不好理解, 于是参照了很多文章, 自己琢磨了下几种简单数据类型的存储.
Number类型
ORACLE对number的存储, 首先是按一定规则进行转换以后以十六进制存储(真正存储当然是二进制, 只是我们dump出来看到的是十六进制)的.
ORACLE数据库中存储的number类型包含3个部分: HEAD部分, DATA部分, 符号位.
对正数来说, 符号位省略, 对0来说, 只有80.
首先来看几个存储的例子, 我们可以用
SELECT DUMP(89,16) FROM dual |
来看到ORACLE对number类型实际存储的结果: Typ=2 Len=2: c1, 5a
当然,如果我们想看十进制的,就用
SELECT DUMP(89,10) FROM dual |
Typ=2 Len=2: 193, 90
123 à C2, 2, 18
123.123 à C2, 2, 18, D, 1F
0 à 80
-123 à 3D, 64, 4E, 66
-0.123 à 3F, 59, 47, 66
HEAD部分为一个字节8位, 表示其大小, 当然也包括正负, 就是前面看到的C2, 3D.
因为设计这种存储格式的时候, 希望以十六进制00-FF来表示所有的number, 所以为了编码的对称, 首先将number分为正负, 所以以00-FF的中间位置80, 也就是十进制的128来表示0, HEAD部分小于80,即为负数,大于80即为正数.
另, 一个数, 都可以表示成(+/-)A.B * 10^(+-)C, 正负A.B * 10的正负C次方.
所以, ORACLE再次对00-80, 80-FF进行对分.
00-3E表示 x <= -1
3F-7F 表示 -1< x <0
81-C0 表示 0< x < 1
C1-FF 表示 1<= x
然后,我们再来看数据部分, ORACLE对十进制的数字是两位两位进行存储的, 例如对1234, ORACLE会分别对12, 34进行存储. 所以只需要对(+-)1-99进行编码
1-99 分别用十六进制2-64表示就是2-100 x=y-1,
-1 – -99用十六进制64 – 2表示就是100-2 x=y-101
而位数的话, 就分别以距+-1两个标准(为了方便,我们以下将以十进制来看)3E, C1(62,193)之差来表示. 至于符号位, 网上有人说是为了方便排序, 并且用的是(+-)1-99都不可能用到的编码66(102)来表示.
例如123, 我们看为(100+23), 比1要多一个百位, 所以HEAD表示为193 + 1 = 194
数据部分用(2, 24)表示, 就是(194,2,24), 转换为十六进制为(C2, 2, 18)
123.123, 我们看为(100+23+0.12+0.0030), 同样HEAD部分为194
数据部分成了(2,24,13,31), 所以就是(C2,2,18,D,1F)
-123, 我们看为(-100-23), 比1多一个百位, 所以HEAD为62-1 = 61
数据部分(64, 78), 所以就是(3D, 64, 4E, 66)
-0.123, 我们看为(-0.12-0.0030), 最高位比-1少一个百分位, 所以HEAD为62+1 = 63
数据部分为(89,71), 所以就是(3F, 59, 47, 66)
其余可类推, 其逆过程也很容易知道了.