今天做dump的时候,对oracle的数字存储规则不是明白,就查了一些资料,这个资料不错
http://www.jlcomp.demon.co.uk/number_format.html (来自 : Jonathan Lewis)
做简单翻译如下:
JL Computer Consultancy---一家咨询公司
How are numbers stored.
ORACLE数据库如何存储数字
November 2001 ---初始版本
Updated: Feb 1020 --更新于2010年2月
I was recently (Nov 2001) asked to explain how to translate a number from Oracle‘s internal database format to a human readable form. I know that I have seen a description somewhere in one of the manuals of how Oracle does this, but it always takes ages to find anything in the manuals when I really want to, so I did a few quick tests with the dump() function, and came up with the following.
在2001年11月份,有人问我一个问题, 如何转化一个oracle内部数据库格式到人类可以理解的格式, 我记得曾经在某份oracle的文档见过如何处理这个事情,但是当我想要找出这份文档时,必定要花费不少的时间, 所以我采用了另外一个方式,快速的利用函数dump做一些测试,然后得到了如下的总结。
If you want to repeat the experiments - the command is::
如果你想要重复这些实验--命令如下
select dump({number},10) from dual; -- decimal dump
以10进制格式导出
select dump({number},16) from dual; -- hex dump
以16进制格式导出
The rules of the format appear to be as follows:
规则转化规则大致如下
Step 1: Precision
第一步,精度
If the internal representation of the number ends in 102 (Hex 0x66)
如果数字的内部表示以102(16进制的0x66)结尾
it is negative
表示这个是个负数
discard the last number (102 / 0x66)
除去最后这个数字(102 / 0x66)
subtract the 2nd through to penultimate numbers from 101 (Hex 0x65)
对于从第二个数字开始到最后一个数字,每个都被101减(101-x),得到一个新的数字
else
it is positive
数字不是以102结尾,那么这个数字就是正数
subtract one from the 2nd through to final numbers
对于从第二个数字开始到最后一个数字,每个减去1得到一个新的数字
end if
Write out each converted number using 2 digits (i.e. leading zeros where needed). Put a decimal point after the first adjusted number.
对于每个经过上述转化过的数字,我们用两位数字表示(举例. 如果需要的话,前面需要加0),在第一个转化过的数字后添加小数点。
Step 2: Scale
第二部 伸缩比例
If the number is negative (ended in 102 / 0x66) then
如果这个数字式负的,那么
The first number of the internal representation is 62 (hex 0x3e) plus the power of 100 to DIVIDE by
那么第一个内部数字为62和某个指数之和,这个指数被用在100之上并且结果是用来做除法的
else
the first number of the internal representation is 193 (hex 0xc1) plus the power of 100 to MULTIPLY by
那么第一个内部数字为193和某个指数之和,这个指数被用在100之上并且结果是用来做乘法的
end if.
There is one special case - zero is represented by a single byte 0x80.
但是有一个特例, 0被表示成一个单字节0x80
Example 1: --样例1
c3 2 2e = 195 2 46
The number is positive (doesn‘t end in 102 / 0x66)
这个数字没有以102结尾,所以是正的
(2,46) --> 01 45 --> 1.45
2-1=1 01
46-1=45 45
这里第一个数字是01, 所以结果为 01.45
195 = 193 + 2 --> multiply by 100 twice
指数部分为2,就是 100的2次方即为 10000
Answer 14,500
所以结果为 : 1.45 * 10000 = 14500
Example 2: ---样例2
be 2e 3d = 190 46 61
The number is positive
这个数字没有以102结尾,所以是正的
(46, 61) --> 45 60 --> 45.60
46-1 =45
61-1 = 60
这里第一个数字是45, 所以结果为 45.60
190 = 193 - 3 --> negative so divide by 100 three times
指数部分为-3,就是 100的负3次方即为 0.0000001
Answer 0.0000456
所以结果为 45.6 * 0.0000001 = 0.0000456
Example 3: --样例3
40 1c 3d 66 = 64 28 61 102
The number is negative (ends in 102 / 0x66)
这个数字以102结尾,所以是负的
(28, 61) --> 73 40 --> 73.40 (101 - 28 = 73 etc.)
101-28 = 73
101-61 = 40
这里第一个数字是73, 所以结果为 -73.40
64 = 62 + 2 --> divide by 100 two times
指数部分为2,就是100的2次方即为 10000
Answer -0.00734
结果就是-73.40 / 10000 = -0.00734
Example 4: --样例4
3c 5d 8 25 43 66 = 60 93 8 37 67 102
The number is negative
这个数字以102结尾,所以是负的
(93, 8, 37, 67) --> 8 93 64 34 --> 8.936434
101-93=8 08
101 -8 =93
101 - 37 = 64
101 - 67 = 34
这里第一个数字是08, 所以结果为 -8.936434
60 = 62 - 2 --> negative so multiple by 100 twice
指数部分为-2,就是100的负2次方即为 0.00001
Answer -89364.34
所以结果为 -8.936434 / 0.00001 = -89364.34
Update Feb 2010:
更新于2010年10月
I’ve been sent an example by Steve Aaron of Barclays Capital show that the “negative number end in 0x66” rule breaks down for very large numbers. Here’s an extract from his demonstration:
我从Barclays Capital公司的 Steve Aaron 处收到一份信息, 显示大的负数不一定以 102 结尾,下面是他给的一个例子
create table numtest (n number);
insert into numtest values (-1111111111111111111111111111111111110703);
column n format 9,999,999,999,999,999,999,999,999,999,999,999,999,999
column dumped format a78
select n, dump(n,16) dumped from numtest;
N
------------------------------------------------------
DUMPED
------------------------------------------------------------------------------
-1,111,111,111,111,111,111,111,111,111,111,111,110,703
Typ=2 Len=21: 2b,5a,5a,5a,5a,5a,5a,5a,5a,5a,5a,5a,5a,5a,5a,5a,5a,5a,5a,5e,62
1 row selected.
Interestingly, the largest precision you can define for a number is number(38) – but if you don’t declare a precision you can get number of up to 40 digits of precision into the database – and it seems to be numbers that go beyond 38 digits of precision where the rule breaks.
有趣的是,最大值的精度已经超过oracle可以定义的最大值38位,你不可能把40位精度的数字插入到数据库中, 验证的结果显示所有超过38位精度的数字都会打破这个规则