1314.oracle中dump函数详解
DUMP函数的输出格式类似:
类型 ,符号/指数位 [数字1,数字2,数字3,…,数字20]
各位的含义如下:
1.类型: Number型,Type=2 (类型代码可以从 Oracle 的文档上查到)
2.长度:指 存储 的字节数
3.符号/指数位
在存储上,Oracle对正数和负数分别进行存储转换:
正数:加1存储(为了避免Null)
负数:被101减,如果总长度小于21个字节,最后加一个102(是为了排序的需要)
指数位换算:
正数:指数=符号/指数位 - 193 (最高位为1是代表正数)
负数:指数=62 - 第一字节
4.从开始是有效的 数据 位
从开始是最高有效位,所存储的数值计算方法为:
将下面计算的结果加起来:
每个乘以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 195 = 1100 0011
13 - 1 = 12 *100^(2-0) 120000
35 - 1 = 34 *100^(2-1) 3400
57 - 1 = 56 *100^(2-2) 56
79 - 1 = 78 *100^(2-3) .78
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,代表为负数) 62= 0011 1110
101 - 89 = 12 *100^(2-0) 120000
101 - 67 = 34 *100^(2-1) 3400
101 - 45 = 56 *100^(2-2) 56
101 - 23 = 78 *100^(2-3) .78
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的情况
转自 http://www.ixora.com.au/notes/number_representation.htm
Internal representation of the NUMBER datatype
As with other datatypes, stored numbers are preceded by a length byte which stores the size of the datum in bytes, or 0xFF for NULLs. The actual data bytes for non-null numbers represent the value in scientific notation. For example, the number 12.3 is represented as +0.123 * 10². The high order bit of the first byte represents the sign. The sign bit is set for positive numbers; and clear for negative numbers. The remainder of the first byte represents the exponent, and then up to 20 bytes may be used to represent the significant digits excluding trailing zeros. This is sometimes called the mantissa.
Each byte of the mantissa normally represents two decimal digits. For positive numbers an offset of 1 is added to avoid null bytes, while for negative numbers an offset of 101 is added to the negated digit pair. Thus a mantissa byte with the decimal value of 100 might represent the digit pair “99” in a positive number, or the digit pair “01” in a negative number. The interpretation must be based on the sign bit. Negative numbers with less than 20 mantissa bytes also have a byte with the (impossible) decimal value 102 appended. I don’t know what purpose this serves.
If there are an odd number of significant digits before the decimal point, the first mantissa byte can only represent 1 digit because the decimal exponent must be even. In this case, the 20-byte mantissa can represent at most 39 decimal digits. However, the last digit may not be accurate if a more precise value has been truncated for storage. This is why the maximum guaranteed precision for Oracle numbers is 38 decimal digits, even though 40 digits can be represented.
The decimal exponent is guaranteed to be even by the alignment of the mantissa. Thus the value stored for the exponent is always halved and is expressed such that the decimal point falls before the first digit of the mantissa. It again represents a pair of decimal digits, this time with an offset of 64 for positive numbers, and 63 for the negated exponent of negative numbers. Thus a set of exponent bits with the decimal value of 65 might represent the exponent +2 in a positive number, or the exponent -4 in a negative number. Please note that the encoding of the exponent is based on the sign of the number, and not on the sign of the exponent itself.
Finally, there are special encodings for zero, and positive and negative infinity . Zero is represented by the single byte 0x80. Negative infinity is represented by 0x00, and positive infinity is represented by the two bytes 0xFF65. These are illustrated in the listing below.
SQL> select n, dump(n,16) from special_numbers;
N DUMP(N,16)
0 Typ=2 Len=1: 80
-~ Typ=2 Len=1: 0
~ Typ=2 Len=2: ff,65
For the rest, the best way to familiarize yourself further with the internal representation of numbers is to use the dump function to examine the representation of some sample values. This is simulated below. Just type a number and then press “Enter” to check out its representation. For example, try to find out why 110 takes one more byte of storage than 1100 despite being a smaller number.
Number:
Representation: Normalized number: +0.1230 * 10^2
Sign bit: 1
Exponent bits: 65 = (64 + 2/2)
First byte: 193
Mantissa digits: 12,30
Mantissa bytes: 13,31
Oracle dump函数的用法
一、函数标准格式:
DUMP(expr[,return_fmt[,start_position][,length]])
基本参数时4个,最少可以填的参数是0个。当完全没有参数时,直接返回null。另外3个参数也都有各自的默认值:
expr:这个参数是要进行分析的表达式(数字或字符串等,可以是各个类型的值)
return_fmt:指返回参数的格式,有5种用法:
1)8:以8进制返回结果的值 2)10:以10进制返回结果的值(默认) 3)16:以16进制返回结果的值 4)17:以单字符的形式返回结果的值 5)1000:以上4种加上1000,表示在返回值中加上当前字符集
start_position:开始进行返回的字符位置
SQL> select dump(‘abc’) from dual;
length:需要返回的字符长度
DUMP(‘ABC’)
Typ=96 Len=3: 97,98,99
SQL> select dump(‘abc’,16) from dual;
DUMP(‘ABC’,16)
Typ=96 Len=3: 61,62,63
SQL> select dump(‘abc’,1016) from dual;
DUMP(‘ABC’,1016)
Typ=96 Len=3 CharacterSet=ZHS16GBK: 61,62,63
SQL> select dump(‘abc’,17,2,2) from dual;
DUMP(‘ABC’,17,2,2
Typ=96 Len=3: b,c
结果的格式一般都是类似:Typ=96 Len=3 [CharacterSet=ZHS16GBK]: 61,62,63
格式解析如下:
1、type
typ表示当前的expr值的类型。如:2表示NUMBER,96表示CHAR。
CODE TYP1 VARCHAR2
2 NUMBER
8 LONG
12 DATE
23 RAW
24 LONG RAW
69 ROWID
96 CHAR
112 CLOB
113 BLOB
114 BFILE
180 TIMESTAMP
181 TIMESTAMP WITH TIMEZONE
182 INTERVAL YEAR TO MONTH
183 INTERVAL DAY TO SECOND
208 UROWID
231 TIMESTAMP WITH LOCAL TIMEZONEselect dump(sysdate,16) from dual;
select dump(rowid,16) from test1;
2、len
len表示该值所占用的字节数。
对于汉字,ZHS16GBK编码一个汉字需要2个字节,UTF8需要3个字节。SQL> select dump(‘多多’,1010) from dual;
DUMP(‘多多’,1010)
Typ=96 Len=4 CharacterSet=ZHS16GBK: 182,224,182,224
3、 Value
具体的存储值。返回的数值就是Oracle在自己内部对前面的这个expr值得存储形式。对于非汉字的普通字符串,可以理解为就是它的ASCII码。
举例证明:
SQL> select dump(‘a=?5’) from dual;DUMP(‘A=?5’)
Typ=96 Len=4: 97,61,63,53
SQL> select chr(97),chr(61),chr(63),chr(53) from dual;
C C C C
a = ? 5
SQL> select ascii(‘a’),ascii(’=’),ascii(’?’),ascii(‘5’) from dual;
ASCII(‘A’) ASCII(’=’) ASCII(’?’) ASCII(‘5’)
97 61 63 53
ASCII码表:
ASCII值 控制字符 ASCII值 控制字符 ASCII值 控制字符 ASCII值 控制字符
0 NUT 32 (space) 64 @ 96 、
1 SOH 33 ! 65 A 97 a
2 STX 34 ” 66 B 98 b
3 ETX 35 # 67 C 99 c
4 EOT 36 $ 68 D 100 d
5 ENQ 37 % 69 E 101 e
6 ACK 38 & 70 F 102 f
7 BEL 39 , 71 G 103 g
8 BS 40 ( 72 H 104 h
9 HT 41 ) 73 I 105 i
10 LF 42 * 74 J 106 j
11 VT 43 + 75 K 107 k
12 FF 44 , 76 L 108 l
13 CR 45 - 77 M 109 m
14 SO 46 . 78 N 110 n
15 SI 47 / 79 O 111 o
16 DLE 48 0 80 P 112 p
17 DCI 49 1 81 Q 113 q
18 DC2 50 2 82 R 114 r
19 DC3 51 3 83 X 115 s
20 DC4 52 4 84 T 116 t
21 NAK 53 5 85 U 117 u
22 SYN 54 6 86 V 118 v
23 TB 55 7 87 W 119 w
24 CAN 56 8 88 X 120 x
25 EM 57 9 89 Y 121 y
26 SUB 58 : 90 Z 122 z
27 ESC 59 ; 91 [ 123 {
28 FS 60 < 92 / 124 |
29 GS 61 = 93 ] 125 }
30 RS 62 > 94 ^ 126 ~
31 US 63 ? 95 — 127 DEL
对于数字的存储,不像字符那么简单,而是应用Oracle自己的一个算法。================ 补充 ========================================================
oracle获取字符串长度函数length()和hengthb() :1.lengthb(string)计算string所占的字节长度:返回字符串的长度,单位是字节
2.length(string)计算string所占的字符长度:返回字符串的长度,单位是字符
3.对于单字节字符,LENGTHB和LENGTH是一样的.
4.如可以用length(‘string’)=lengthb(‘string’)判断字符串是否含有中文。注:一个汉字在Oracle数据库里占多少字节跟数据库的字符集有关,UTF8时,长度为三。
select length(‘箱’) from dual --返回1
select lengthb(‘箱’) from dual --返回2
select length(‘CC’) from dual --返回2
select lengthb(‘CC’) from dual --返回2SQL> select length(‘箱’) from dual;
LENGTH(‘箱’)
SQL> select lengthb(‘箱’) from dual;
LENGTHB(‘箱’)
SQL> select length(‘CC’) from dual;
LENGTH(‘CC’)
SQL> select lengthb(‘CC’) from dual;
LENGTHB(‘CC’)
oracle转换为16进制,Oracle的十进制和16进制转换函数
在数据库中,常常需要将10进制转16进制,又会需要将16进制转10进制。有两个使用PL/SQL开发的函数,可以方便使用。
create or replace function f_dec2hex(p_int in varchar2) return varchar2 is– 对象名称: f_dec2hex
– 对象描述: 十进制转换十六进制
– 输入参数: p_str 十进制字符串
– 返回结果: 十六进制字符串
– 测试用例: select f_dec2hex(45217) from dual;
sql> select f_dec2hex(45217) from dual;
f_dec2hex(45217)v_return varchar2(4000);
begin
select upper(trim(to_char(p_int, ‘xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx’))) into v_return from dual;
return v_return;
exception
when others then
return null;
end f_dec2hex;
create or replace function f_hex2dec(p_str in varchar2) return varchar2 is– 对象名称: f_hex2dec
– 对象描述: 十六进制转换十进制
– 输入参数: p_str 十六进制字符串
– 返回结果: 十进制字符串
– 测试用例: select f_hex2dec(‘b0a1’) from dual;
sql> select f_hex2dec(‘b0a1’) from dual;
f_hex2dec(‘b0a1’)45217
v_return varchar2(4000);
begin
select sum(data1) into v_return
from (select (case upper(substr(p_str, rownum, 1))
when ‘a’ then ‘10’
when ‘b’ then ‘11’
when ‘c’ then ‘12’
when ‘d’ then ‘13’
when ‘e’ then ‘14’
when ‘f’ then ‘15’
else substr(p_str, rownum, 1)
end) * power(16, length(p_str) - rownum) data1
from dual
connect by rownum <= length(p_str));
return v_return;
exception
when others then
return null;
end f_hex2dec;
在使用ZHS16GBK的字符集编码数据库中,汉字“啊”的ASCII码就是45217。
SQL> select ascii(‘啊’) from dual;
ASCII(‘啊’)45217
这两个字节也符合GBK字符集编码中的描述,可参见字符集GB2312的理解一文。
转换成16进制,就是B0A1。它的第一个字节(高位字节)是B0,第二个字节即低位字节是A1。
SQL> select f_dec2hex(45217) from dual;
F_DEC2HEX(45217)How Oracle Store Number internal?
作者:eygle |English Version 【转载时请以超链接形式标明文章出处和作者信息及本声明】
链接: http://www.eygle.com/archives/2005/12/how_oracle_stor.htmlOracle在数据库内部通过相应的算法转换来进行数据存储,本文简单介绍Oracle的Number型数值存储及转换.这个内容是为了回答留言板上的2119号问题.
我们可以通过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的情况。
对于2119号提问,第一个问题是:
1.请问为什么193,2各代表什么意思?
从上面就可以看到答案了.
2.还有NUMBER数字类型为什么有2个字节的长度呢?
对于这个问题,我想我们应该知道,所有数据类型最终在计算机里都以二进制存储,实际上所谓的数据类型都是我们定义的.所以存储只由算法决定.
所以这个问题是不成立的.比如:
SQL> select dump(110) from dual;
DUMP(110)Typ=2 Len=3: 194,2,11
SQL> select dump(1100) from dual;