楼主: yangtingkun

[精华] Oracle基本数据类型存储格式浅析

[复制链接]
论坛徽章:
226
BLOG每日发帖之星
日期:2010-02-11 01:01:06紫蛋头
日期:2013-01-12 23:45:222013年新春福章
日期:2013-02-25 14:51:24问答徽章
日期:2013-10-17 18:06:40优秀写手
日期:2013-12-18 09:29:10马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上加薪
日期:2014-02-19 11:55:14
31#
 楼主| 发表于 2005-3-21 18:01 | 只看该作者
Dump file e:\oracle\admin\test\udump\test_ora_3580.trc
Mon Mar 21 17:36:06 2005
ORACLE V9.2.0.1.0 - Production vsnsta=0
vsnsql=12 vsnxtr=3
Windows 2000 Version 5.0 Service Pack 4, CPU type 586
Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
With the Partitioning, Oracle Label Security, OLAP and Oracle Data Mining options
JServer Release 9.2.0.1.0 - Production
Windows 2000 Version 5.0 Service Pack 4, CPU type 586
Instance name: test

Redo thread mounted by this instance: 1

Oracle process number: 10

Windows thread id: 3580, image: ORACLE.EXE


*** 2005-03-21 17:36:06.000
*** SESSION ID12.11) 2005-03-21 17:36:06.000
Start dump data blocks tsn: 8 file#: 9 minblk 85572 maxblk 85572
buffer tsn: 8 rdba: 0x02414e44 (9/85572)
scn: 0x0000.404340df seq: 0x01 flg: 0x04 tail: 0x40df0601
frmt: 0x02 chkval: 0x0978 type: 0x06=trans data
Block header dump:  0x02414e44
Object id on Block? Y
seg/obj: 0x1cbe  csc: 0x00.404340df  itc: 2  flg: O  typ: 1 - DATA
     fsl: 0  fnx: 0x0 ver: 0x01

Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x000a.05e.00000082  0x008000ae.0078.02  C---    0  scn 0x0000.404340a1
0x02   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000

data_block_dump,data header at 0xdf1105c
===============
tsiz: 0x7a0
hsiz: 0x2c
pbl: 0x0df1105c
bdba: 0x02414e44
     76543210
flag=--------
ntab=1
nrow=13
frre=-1
fsbo=0x2c
fseo=0x375
avsp=0x349
tosp=0x349
0xeti[0]        nrow=13        offs=0
0x12ri[0]        offs=0x375
0x14ri[1]        offs=0x3c8
0x16ri[2]        offs=0x413
0x18ri[3]        offs=0x460
0x1ari[4]        offs=0x4b2
0x1cri[5]        offs=0x504
0x1eri[6]        offs=0x558
0x20ri[7]        offs=0x5b1
0x22ri[8]        offs=0x601
0x24:pri[9]        offs=0x651
0x26:pri[10]        offs=0x6a3
0x28:pri[11]        offs=0x6fa
0x2a:pri[12]        offs=0x74e
block_row_dump:
tab 0, row 0, @0x375
tl: 83 fb: --H-FL-- lb: 0x0  cc: 13
col  0: [ 3]  48 52 31
col  1: [12]  4a 48 49 53 54 5f 4a 4f 42 5f 49 58
col  2: *NULL*
col  3: [ 3]  c2 40 04
col  4: [ 3]  c2 40 04
col  5: [ 5]  49 4e 44 45 58
col  6: [ 7]  78 68 0a 15 10 1e 32
col  7: [ 7]  78 68 0a 15 10 1e 32
col  8: [19]  32 30 30 34 2d 31 30 2d 32 31 3a 31 35 3a 32 39 3a 34 39
col  9: [ 5]  56 41 4c 49 44
col 10: [ 1]  4e
col 11: [ 1]  4e
col 12: [ 1]  4e
tab 0, row 1, @0x3c8
tl: 75 fb: --H-FL-- lb: 0x0  cc: 13
col  0: [ 3]  48 52 31
col  1: [ 4]  4a 4f 42 53
col  2: *NULL*
col  3: [ 3]  c2 3f 5a
col  4: [ 3]  c2 3f 5a
col  5: [ 5]  54 41 42 4c 45
col  6: [ 7]  78 68 0a 15 10 1e 29
col  7: [ 7]  78 68 0a 15 12 04 08
col  8: [19]  32 30 30 34 2d 31 30 2d 32 31 3a 31 35 3a 32 39 3a 34 30
col  9: [ 5]  56 41 4c 49 44
col 10: [ 1]  4e
col 11: [ 1]  4e
col 12: [ 1]  4e
tab 0, row 2, @0x413
tl: 77 fb: --H-FL-- lb: 0x0  cc: 13
col  0: [ 3]  48 52 31
col  1: [ 7]  4a 4f 42 53 24 52 50
col  2: *NULL*
col  3: [ 3]  c2 40 1a
col  4: *NULL*
col  5: [ 7]  50 41 43 4b 41 47 45
col  6: [ 7]  78 68 0a 15 12 03 0c
col  7: [ 7]  78 68 0b 10 14 06 1b
col  8: [19]  32 30 30 34 2d 31 30 2d 32 31 3a 31 37 3a 30 32 3a 31 31
col  9: [ 5]  56 41 4c 49 44
col 10: [ 1]  4e
col 11: [ 1]  4e
col 12: [ 1]  4e
tab 0, row 3, @0x460
tl: 82 fb: --H-FL-- lb: 0x0  cc: 13
col  0: [ 3]  48 52 31
col  1: [ 7]  4a 4f 42 53 24 52 50
col  2: *NULL*
col  3: [ 3]  c2 40 1b
col  4: *NULL*
col  5: [12]  50 41 43 4b 41 47 45 20 42 4f 44 59
col  6: [ 7]  78 68 0a 15 12 03 0c
col  7: [ 7]  78 68 0b 10 14 06 1b
col  8: [19]  32 30 30 34 2d 31 30 2d 32 31 3a 31 37 3a 30 32 3a 31 31
col  9: [ 5]  56 41 4c 49 44
col 10: [ 1]  4e
col 11: [ 1]  4e
col 12: [ 1]  4e
tab 0, row 4, @0x4b2
tl: 82 fb: --H-FL-- lb: 0x0  cc: 13
col  0: [ 3]  48 52 31
col  1: [11]  4a 4f 42 5f 48 49 53 54 4f 52 59
col  2: *NULL*
col  3: [ 3]  c2 3f 60
col  4: [ 3]  c2 3f 60
col  5: [ 5]  54 41 42 4c 45
col  6: [ 7]  78 68 0a 15 10 1e 2c
col  7: [ 7]  78 68 0a 15 12 04 09
col  8: [19]  32 30 30 34 2d 31 30 2d 32 31 3a 31 35 3a 32 39 3a 34 33
col  9: [ 5]  56 41 4c 49 44
col 10: [ 1]  4e
col 11: [ 1]  4e
col 12: [ 1]  4e
tab 0, row 5, @0x504
tl: 84 fb: --H-FL-- lb: 0x0  cc: 13
col  0: [ 3]  48 52 31
col  1: [14]  4a 4f 42 5f 48 49 53 54 4f 52 59 24 52 50
col  2: *NULL*
col  3: [ 3]  c2 40 1c
col  4: *NULL*
col  5: [ 7]  50 41 43 4b 41 47 45
col  6: [ 7]  78 68 0a 15 12 03 0d
col  7: [ 7]  78 68 0b 10 14 06 1b
col  8: [19]  32 30 30 34 2d 31 30 2d 32 31 3a 31 37 3a 30 32 3a 31 32
col  9: [ 5]  56 41 4c 49 44
col 10: [ 1]  4e
col 11: [ 1]  4e
col 12: [ 1]  4e
tab 0, row 6, @0x558
tl: 89 fb: --H-FL-- lb: 0x0  cc: 13
col  0: [ 3]  48 52 31
col  1: [14]  4a 4f 42 5f 48 49 53 54 4f 52 59 24 52 50
col  2: *NULL*
col  3: [ 3]  c2 40 1d
col  4: *NULL*
col  5: [12]  50 41 43 4b 41 47 45 20 42 4f 44 59
col  6: [ 7]  78 68 0a 15 12 03 0d
col  7: [ 7]  78 68 0b 10 14 06 1c
col  8: [19]  32 30 30 34 2d 31 30 2d 32 31 3a 31 37 3a 30 32 3a 31 32
col  9: [ 5]  56 41 4c 49 44
col 10: [ 1]  4e
col 11: [ 1]  4e
col 12: [ 1]  4e
tab 0, row 7, @0x5b1
tl: 80 fb: --H-FL-- lb: 0x0  cc: 13
col  0: [ 3]  48 52 31
col  1: [ 9]  4a 4f 42 5f 49 44 5f 50 4b
col  2: *NULL*
col  3: [ 3]  c2 3f 5b
col  4: [ 3]  c2 3f 5b
col  5: [ 5]  49 4e 44 45 58
col  6: [ 7]  78 68 0a 15 10 1e 29
col  7: [ 7]  78 68 0a 15 10 1e 29
col  8: [19]  32 30 30 34 2d 31 30 2d 32 31 3a 31 35 3a 32 39 3a 34 30
col  9: [ 5]  56 41 4c 49 44
col 10: [ 1]  4e
col 11: [ 1]  4e
col 12: [ 1]  4e
tab 0, row 8, @0x601
tl: 80 fb: --H-FL-- lb: 0x0  cc: 13
col  0: [ 3]  48 52 31
col  1: [ 9]  4c 4f 43 41 54 49 4f 4e 53
col  2: *NULL*
col  3: [ 3]  c2 3f 54
col  4: [ 3]  c2 3f 54
col  5: [ 5]  54 41 42 4c 45
col  6: [ 7]  78 68 0a 15 10 1e 25
col  7: [ 7]  78 68 0a 15 12 04 09
col  8: [19]  32 30 30 34 2d 31 30 2d 32 31 3a 31 35 3a 32 39 3a 33 36
col  9: [ 5]  56 41 4c 49 44
col 10: [ 1]  4e
col 11: [ 1]  4e
col 12: [ 1]  4e
tab 0, row 9, @0x651
tl: 82 fb: --H-FL-- lb: 0x0  cc: 13
col  0: [ 3]  48 52 31
col  1: [12]  4c 4f 43 41 54 49 4f 4e 53 24 52 50
col  2: *NULL*
col  3: [ 3]  c2 40 1e
col  4: *NULL*
col  5: [ 7]  50 41 43 4b 41 47 45
col  6: [ 7]  78 68 0a 15 12 03 0e
col  7: [ 7]  78 68 0b 10 14 06 1c
col  8: [19]  32 30 30 34 2d 31 30 2d 32 31 3a 31 37 3a 30 32 3a 31 33
col  9: [ 5]  56 41 4c 49 44
col 10: [ 1]  4e
col 11: [ 1]  4e
col 12: [ 1]  4e
tab 0, row 10, @0x6a3
tl: 87 fb: --H-FL-- lb: 0x0  cc: 13
col  0: [ 3]  48 52 31
col  1: [12]  4c 4f 43 41 54 49 4f 4e 53 24 52 50
col  2: *NULL*
col  3: [ 3]  c2 40 1f
col  4: *NULL*
col  5: [12]  50 41 43 4b 41 47 45 20 42 4f 44 59
col  6: [ 7]  78 68 0a 15 12 03 0e
col  7: [ 7]  78 68 0b 10 14 06 1c
col  8: [19]  32 30 30 34 2d 31 30 2d 32 31 3a 31 37 3a 30 32 3a 31 33
col  9: [ 5]  56 41 4c 49 44
col 10: [ 1]  4e
col 11: [ 1]  4e
col 12: [ 1]  4e
tab 0, row 11, @0x6fa
tl: 84 fb: --H-FL-- lb: 0x0  cc: 13
col  0: [ 3]  48 52 31
col  1: [13]  4c 4f 43 41 54 49 4f 4e 53 5f 53 45 51
col  2: *NULL*
col  3: [ 3]  c2 3f 56
col  4: *NULL*
col  5: [ 8]  53 45 51 55 45 4e 43 45
col  6: [ 7]  78 68 0a 15 10 1e 27
col  7: [ 7]  78 68 0a 15 10 1e 27
col  8: [19]  32 30 30 34 2d 31 30 2d 32 31 3a 31 35 3a 32 39 3a 33 38
col  9: [ 5]  56 41 4c 49 44
col 10: [ 1]  4e
col 11: [ 1]  4e
col 12: [ 1]  4e
tab 0, row 12, @0x74e
tl: 82 fb: --H-FL-- lb: 0x0  cc: 13
col  0: [ 3]  48 52 31
col  1: [11]  4c 4f 43 5f 43 49 54 59 5f 49 58
col  2: *NULL*
col  3: [ 3]  c2 40 07
col  4: [ 3]  c2 40 07
col  5: [ 5]  49 4e 44 45 58
col  6: [ 7]  78 68 0a 15 10 1e 33
col  7: [ 7]  78 68 0a 15 10 1e 33
col  8: [19]  32 30 30 34 2d 31 30 2d 32 31 3a 31 35 3a 32 39 3a 35 30
col  9: [ 5]  56 41 4c 49 44
col 10: [ 1]  4e
col 11: [ 1]  4e
col 12: [ 1]  4e
end_of_block_dump
End dump data blocks tsn: 8 file#: 9 minblk 85572 maxblk 85572

我取的是最大的rowid,必然是最后一个block的最后一条记录。

使用道具 举报

回复
论坛徽章:
3
授权会员
日期:2005-10-30 17:05:33会员2006贡献徽章
日期:2006-04-17 13:46:34ITPUB元老
日期:2006-09-11 15:36:37
32#
发表于 2005-3-22 15:14 | 只看该作者
謝謝您楊兄﹐

已明白塊和文件的共用情況。在sgement 中的塊 ID 達到 65536 時﹐
會將 trunc(block_id/65536) 的值加到 file id 中一起存儲在 數據文件中的那兩位﹐
而將 mod(block_id,65536) 的值存在 block id 的那兩位。
所以就會有說 ﹐block id 的 第三位要小于 64 以防當成 file id 來存儲﹐。
所以 block 最大的 id 為 65536*63+ 65536 =4194304﹐對吧

然而 d.c.b.a  在這而所講的我又有點不表楚了﹐也是一個一直很迷惑的地方﹐借此請教您一下﹕
最初由 dcba 发布
[B]D
上面的block所在的data_object_id应当是7358吧

rdba = ((2 * 256 + 65) * 256 + 78) * 256 + 68
高10bit是rfn, 低22bit是block id
slot = 12, 这一行在block中的row index的位置是12行,可以dump看一下.
[/B]


他這里的 rdba 是怎么回事﹐他是怎么換算的呀﹖想請您指點一下。

此外﹐我們在 dump block 時﹐在 trace 文件中也可以看到如您下面的文件中的 如﹕

最初由 yangtingkun 发布
[B]Dump file e:\oracle\admin\test\udump\test_ora_3580.trc
Mon Mar 21 17:36:06 2005
..........
.......................

Start dump data blocks tsn: 8 file#: 9 minblk 85572 maxblk 85572
buffer tsn: 8 rdba: 0x02414e44 (9/85572)
scn: 0x0000.404340df seq: 0x01 flg: 0x04 tail: 0x40df0601
frmt: 0x02 chkval: 0x0978 type: 0x06=trans data
Block header dump:  0x02414e44
..................... [/B]


這中間的  rdba: 0x02414e44 (9/85572)

換出來的得到 file id 為 9 ﹐block id 為 85572 是不是就是和上面 dcba 講的是一樣的呀。

我知道 rdba 中的前面三位是表示 file id 的﹐而后面的是表示 block id 的。
那么 024 轉成二進制:0000 0010 0100 ,那么 擷取中的的 1001 變成 10 制的數就是 9了。
但不知道怎么算的﹐碰到這種情況還可以蒙出來﹐但像﹕
Start dump data blocks tsn: 51 file#: 65 minblk 56 maxblk 56
buffer tsn: 51 rdba: 0x10400038 (65/56)


Start dump data blocks tsn: 1 file#: 2 minblk 45 maxblk 45
buffer tsn: 1 rdba: 0x0080002d (2/45)
就不是很好蒙了,呵。。。

所以也想向您 請教一下。

謝謝。

使用道具 举报

回复
论坛徽章:
3
授权会员
日期:2005-10-30 17:05:33会员2006贡献徽章
日期:2006-04-17 13:46:34ITPUB元老
日期:2006-09-11 15:36:37
33#
发表于 2005-3-25 10:02 | 只看该作者
有明白 rdba 的意義了﹐是取 轉換 二進制后 取前 10 碼作為 file_id ﹐后面的作為 block_id。

謝謝啦》。

使用道具 举报

回复
论坛徽章:
22
2010新春纪念徽章
日期:2010-03-01 11:08:33马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:142012新春纪念徽章
日期:2012-02-13 15:08:092012新春纪念徽章
日期:2012-02-13 15:08:092012新春纪念徽章
日期:2012-02-13 15:08:092012新春纪念徽章
日期:2012-02-13 15:08:092012新春纪念徽章
日期:2012-02-13 15:08:09
34#
发表于 2005-3-26 12:46 | 只看该作者
最初由 zhang_yong88 发布
[B]有明白 rdba 的意義了﹐是取 轉換 二進制后 取前 10 碼作為 file_id ﹐后面的作為 block_id。

謝謝啦》。 [/B]


file_no去rdba的前10位数据, 刚好与Oracle的file_no最大为1024相吻合.
0x0080002d
编程2进制为.

0000 0000 10 00 0000 0000 0000 0010 1101
file_no = 1 * 2 = 2
block_no = 1 * 32 + 1 * 8 + 1 * 4 + 1 = 45

0x02414e44
0000 0010 01  00 0001 0100 1110 0100 0100
file_no = 1 * 8 + 1 = 9
block_no = 64 * 1024 + 16 * 1024 + 2 * 1024 + 1024 + 512 + 64 + 4 = 85572

使用道具 举报

回复
论坛徽章:
42
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:022011新春纪念徽章
日期:2011-01-25 15:42:332011新春纪念徽章
日期:2011-01-25 15:42:56管理团队成员
日期:2011-05-07 01:45:08ITPUB十周年纪念徽章
日期:2011-11-01 16:20:282012新春纪念徽章
日期:2012-02-13 15:09:232012新春纪念徽章
日期:2012-02-13 15:09:232012新春纪念徽章
日期:2012-02-13 15:09:232012新春纪念徽章
日期:2012-02-13 15:09:232012新春纪念徽章
日期:2012-02-13 15:09:23
35#
发表于 2005-3-26 22:56 | 只看该作者
我还以为我说得很清楚了,不好意思了。

使用道具 举报

回复
论坛徽章:
3
授权会员
日期:2005-10-30 17:05:33会员2006贡献徽章
日期:2006-04-17 13:46:34ITPUB元老
日期:2006-09-11 15:36:37
36#
发表于 2005-3-27 16:06 | 只看该作者
最初由 jametong 发布
[B]

file_no去rdba的前10位数据, 刚好与Oracle的file_no最大为1024相吻合.
0x0080002d
编程2进制为.

0000 0000 10 00 0000 0000 0000 0010 1101
file_no = 1 * 2 = 2
block_no = 1 * 32 + 1 * 8 + 1 * 4 + 1 = 45

0x02414e44
0000 0010 01  00 0001 0100 1110 0100 0100
file_no = 1 * 8 + 1 = 9
block_no = 64 * 1024 + 16 * 1024 + 2 * 1024 + 1024 + 512 + 64 + 4 = 85572 [/B]


謝謝 d.c.b.a 。。。

使用道具 举报

回复
论坛徽章:
7
每日论坛发贴之星
日期:2005-06-23 01:01:12授权会员
日期:2005-11-09 18:19:55会员2006贡献徽章
日期:2006-04-17 13:46:34生肖徽章:虎
日期:2006-09-26 17:34:28生肖徽章:兔
日期:2006-09-26 17:34:43ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44奥运会纪念徽章:击剑
日期:2008-04-23 15:45:13
37#
发表于 2005-4-8 12:01 | 只看该作者
高啊,实在是高!

使用道具 举报

回复
论坛徽章:
226
BLOG每日发帖之星
日期:2010-02-11 01:01:06紫蛋头
日期:2013-01-12 23:45:222013年新春福章
日期:2013-02-25 14:51:24问答徽章
日期:2013-10-17 18:06:40优秀写手
日期:2013-12-18 09:29:10马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上加薪
日期:2014-02-19 11:55:14
38#
 楼主| 发表于 2005-4-10 11:14 | 只看该作者

解析Oracle各种数据类型

前一阵写了Oracle基本数据类型存储格式浅析,对各种数量类型的存储进行了简单的描述,而后又写了一篇repare包修复坏块,其中自己写了一个程序包来恢复DUMP后的数据。但是那个程序包主要是针对repare包生成的结果的,因此通用性不好。

这篇文章将那个程序包修改并简化,变为一个函数。下面给出这个函数的实现和使用例子:

[PHP]
SQL> CREATE OR REPLACE FUNCTION F_GET_FROM_DUMP
  2  (
  3   P_DUMP IN VARCHAR2,
  4   P_TYPE IN VARCHAR2
  5  )
  6  RETURN VARCHAR2 AS
  7   V_LENGTH_STR VARCHAR2(10);
  8   V_LENGTH NUMBER DEFAULT 7;
  9   V_DUMP_ROWID VARCHAR2(30000);
10   
11   V_DATE_STR VARCHAR2(100);
12   TYPE T_DATE IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
13   V_DATE T_DATE;
14   
15   FUNCTION F_ADD_PREFIX_ZERO (P_STR IN VARCHAR2, P_POSITION IN NUMBER) RETURN VARCHAR2
16   AS
17    V_STR VARCHAR2(30000) := P_STR;
18    V_POSITION NUMBER := P_POSITION;
19    V_STR_PART VARCHAR2(2);
20    V_RETURN VARCHAR2(30000);
21   BEGIN
22    WHILE (V_POSITION != 0) LOOP
23     V_STR_PART := SUBSTR(V_STR, 1, V_POSITION - 1);
24     V_STR := SUBSTR(V_STR, V_POSITION + 1);
25   
26     IF V_POSITION = 2 THEN
27      V_RETURN := V_RETURN || '0' || V_STR_PART;
28     ELSIF V_POSITION = 3 THEN
29      V_RETURN := V_RETURN || V_STR_PART;
30     ELSE
31      RAISE_APPLICATION_ERROR(-20002, 'DUMP ERROR CHECK THE INPUT ROWID');
32     END IF;
33   
34     V_POSITION := INSTR(V_STR, ',');
35    END LOOP;
36    RETURN REPLACE(V_RETURN , ',');
37   END F_ADD_PREFIX_ZERO;
38  
39  BEGIN
40   IF SUBSTR(P_DUMP, 1, 3) = 'Typ' THEN
41    V_DUMP_ROWID := SUBSTR(P_DUMP, INSTR(P_DUMP, ':') + 2);
42   ELSE
43    V_DUMP_ROWID := P_DUMP;
44   END IF;
45   
46   IF P_TYPE = 'VARCHAR2' OR P_TYPE = 'CHAR' THEN
47  
48    V_DUMP_ROWID :=F_ADD_PREFIX_ZERO(V_DUMP_ROWID || ',', INSTR(V_DUMP_ROWID, ','));
49   
50    RETURN(UTL_RAW.CAST_TO_VARCHAR2(V_DUMP_ROWID));
51   
52   ELSIF P_TYPE = 'NUMBER' THEN
53  
54    V_DUMP_ROWID :=F_ADD_PREFIX_ZERO(V_DUMP_ROWID || ',', INSTR(V_DUMP_ROWID, ','));
55  
56    RETURN(TO_CHAR(UTL_RAW.CAST_TO_NUMBER(V_DUMP_ROWID)));
57   
58   ELSIF P_TYPE = 'DATE' THEN
59   
60    V_DUMP_ROWID := ',' || V_DUMP_ROWID || ',';
61   
62    FOR I IN 1..7 LOOP
63     V_DATE(I) := TO_NUMBER(SUBSTR(V_DUMP_ROWID, INSTR(V_DUMP_ROWID, ',', 1, I) + 1,
64      INSTR(V_DUMP_ROWID, ',', 1, I + 1) - INSTR(V_DUMP_ROWID, ',', 1, I) - 1), 'XXX');
65    END LOOP;
66  
67    V_DATE(1) := V_DATE(1) - 100;
68    V_DATE(2) := V_DATE(2) - 100;
69  
70    IF ((V_DATE(1) < 0) OR (V_DATE(2) < 0)) THEN
71     V_DATE_STR := '-' || LTRIM(TO_CHAR(ABS(V_DATE(1)), '00')) || LTRIM(TO_CHAR(ABS(V_DATE(2)), '
00'));
72    ELSE
73     V_DATE_STR := LTRIM(TO_CHAR(ABS(V_DATE(1)), '00')) || LTRIM(TO_CHAR(ABS(V_DATE(2)),'00'));
74    END IF;
75  
76    V_DATE_STR := V_DATE_STR || '-' || TO_CHAR(V_DATE(3)) || '-' || TO_CHAR(V_DATE(4)) || ' ' ||
77     TO_CHAR(V_DATE(5) - 1) || ':' || TO_CHAR(V_DATE(6) - 1) || ':' || TO_CHAR(V_DATE(7) - 1);
78    RETURN (V_DATE_STR);
79   
80   ELSIF ((P_TYPE LIKE 'TIMESTAMP(_)') OR (P_TYPE = 'TIMESTAMP')) THEN
81   
82    V_DUMP_ROWID := ',' || V_DUMP_ROWID || ',';
83   
84    FOR I IN 1..11 LOOP
85     V_DATE(I) := TO_NUMBER(SUBSTR(V_DUMP_ROWID, INSTR(V_DUMP_ROWID, ',', 1, I) + 1,
86      INSTR(V_DUMP_ROWID, ',', 1, I + 1) - INSTR(V_DUMP_ROWID, ',', 1, I) - 1), 'XXX');
87    END LOOP;
88   
89    V_DATE(1) := V_DATE(1) - 100;
90    V_DATE(2) := V_DATE(2) - 100;
91   
92    IF ((V_DATE(1) < 0) OR (V_DATE(2) < 0)) THEN
93     V_DATE_STR := '-' || LTRIM(TO_CHAR(ABS(V_DATE(1)), '00')) || LTRIM(TO_CHAR(ABS(V_DATE(2)), '
00'));
94    ELSE
95     V_DATE_STR := LTRIM(TO_CHAR(ABS(V_DATE(1)), '00')) || LTRIM(TO_CHAR(ABS(V_DATE(2)),'00'));
96    END IF;
97   
98    V_DATE_STR := V_DATE_STR || '-' || TO_CHAR(V_DATE(3)) || '-' || TO_CHAR(V_DATE(4)) || ' ' ||
99     TO_CHAR(V_DATE(5) - 1) || ':' || TO_CHAR(V_DATE(6) - 1) || ':' || TO_CHAR(V_DATE(7) - 1) ||
'.' ||
100     SUBSTR(TO_CHAR(V_DATE(8) * POWER(256, 3) + V_DATE(9) * POWER(256, 2) + V_DATE(10) * 256 + V_
DATE(11)),
101      1, NVL(TO_NUMBER(SUBSTR(P_TYPE, 11, 1)), 6));
102    RETURN (V_DATE_STR);
103   
104   ELSIF P_TYPE = 'RAW' THEN
105   
106    V_DUMP_ROWID :=F_ADD_PREFIX_ZERO(V_DUMP_ROWID || ',', INSTR(V_DUMP_ROWID, ','));
107   
108    RETURN(V_DUMP_ROWID);
109   
110   ELSIF P_TYPE = 'ROWID' THEN
111   
112    V_DUMP_ROWID :=F_ADD_PREFIX_ZERO(V_DUMP_ROWID || ',', INSTR(V_DUMP_ROWID, ','));
113     RETURN (DBMS_ROWID.ROWID_CREATE(
114     1,
115     TO_NUMBER(SUBSTR(V_DUMP_ROWID, 1, 8), 'XXXXXXXXXXX'),
116     TRUNC(TO_NUMBER(SUBSTR(V_DUMP_ROWID, 9, 4), 'XXXXXX')/64),
117     TO_NUMBER(MOD(TO_NUMBER(SUBSTR(V_DUMP_ROWID, 9, 4), 'XXXXXX'), 64) ||
118      TO_NUMBER(SUBSTR(V_DUMP_ROWID, 13, 4), 'XXXXXXXXXXX')),
119     TO_NUMBER(SUBSTR(V_DUMP_ROWID, 17, 4), 'XXXXXX')));   
120   
121   ELSE
122    RAISE_APPLICATION_ERROR(-20001, 'TYPE NOT VALID OR CAN''T TRANSALTE ' || P_TYPE || ' TYPE');
123   END IF;
124  
125  END;
126  /


函数已创建。


SQL> SELECT F_GET_FROM_DUMP(DUMP(2342.231, 16), 'NUMBER') FROM DUAL;


F_GET_FROM_DUMP(DUMP(2342.231,16),'NUMBER')
--------------------------------------------
2342.231


SQL> SELECT F_GET_FROM_DUMP(DUMP(-0.00234, 16), 'NUMBER') FROM DUAL;


F_GET_FROM_DUMP(DUMP(-0.00234,16),'NUMBER')
---------------------------------------------
-.00234


SQL> SELECT F_GET_FROM_DUMP(DUMP('23EJF.M>', 16), 'VARCHAR2') FROM DUAL;


F_GET_FROM_DUMP(DUMP('23EJF.M>',16),'VARCHAR2')
------------------------------------------------
23EJF.M>


SQL> SELECT F_GET_FROM_DUMP(DUMP('测试', 16), 'VARCHAR2') FROM DUAL;


F_GET_FROM_DUMP(DUMP('测试',16),'VARCHAR2')
------------------------------------------------
测试
.
[/PHP]

由于在SQL中直接使用DATE类型和Oracle存储的不一致,因此解析DATE和TIMESTAMP类型需要通过表中存储的数据,而不能通过SQL中的TO_DATE或SYSDATE。在SQL中直接使用的DATE类型的解析由于意义不大而没有给出。关于在SQL中直接使用DATE和存储在表中的DATE类型的区别,可以参考我的Oracle基本数据类型存储格式浅析中日期类型的文章,连接在文章末尾给出。

[PHP]
SQL> CREATE TABLE TEST_DATE (TIME1 DATE, TIME2 TIMESTAMP, TIME3 TIMESTAMP(9));


表已创建。


SQL> INSERT INTO TEST_DATE VALUES (SYSDATE,
  2  TO_TIMESTAMP('2004-4-9 22:59:43.234232222', 'YYYY-MM-DD HH24:MI:SS.FF'),
  3  TO_TIMESTAMP('2004-4-9 22:59:43.234232222', 'YYYY-MM-DD HH24:MI:SS.FF'));


已创建 1 行。


SQL> COL GET_DUMP FORMAT A30
SQL> ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';


会话已更改。


SQL> SELECT TIME1, F_GET_FROM_DUMP(DUMP(TIME1, 16), 'DATE') GET_DUMP FROM TEST_DATE;


TIME1               GET_DUMP
------------------- ------------------------------
2005-04-09 23:00:04 2005-4-9 23:0:4


SQL> ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF';


会话已更改。


SQL> SELECT TIME2, F_GET_FROM_DUMP(DUMP(TIME2, 16), 'TIMESTAMP') GET_DUMP
  2  FROM TEST_DATE;


TIME2                              GET_DUMP
---------------------------------- ------------------------
2004-04-09 22:59:43.234232         2004-4-9 22:59:43.234232


SQL> SELECT TIME3, F_GET_FROM_DUMP(DUMP(TIME3, 16), 'TIMESTAMP(9)') GET_DUMP
  2  FROM TEST_DATE;


TIME3                              GET_DUMP
---------------------------------- ------------------------
2004-04-09 22:59:43.234232222      2004-4-9 22:59:43.234232222
.
[/PHP]

对于SQL中直接使用的DATE类型会报错:

[PHP]
SQL> SELECT SYSDATE, F_GET_FROM_DUMP(DUMP(SYSDATE, 16), 'DATE') GET_DUMP FROM DUAL;


SYSDATE             GET_DUMP
------------------- ------------------------------
2005-04-09 23:04:58 -###93-4-9 22:3:57


SQL> SELECT RAW_DATA, F_GET_FROM_DUMP(DUMP(RAW_DATA, 16), 'RAW') GET_DUMP
  2  FROM TEST_RAW;


RAW_DATA             GET_DUMP
-------------------- ------------------------------
F5021C               f5021c
.
[/PHP]

这个函数目前支持CHAR、VARCHAR2、NUMBER、DATE、TIMESTAMP和RAW类型,上面分别举了例子。


函数的第一个参数可以是DUMP函数的输出,也可以是数据库中的直接存储信息(需要用逗号分隔)。

[PHP]
SQL> SELECT F_GET_FROM_DUMP('Typ=96 Len=4: 74,65,73,74', 'VARCHAR2') GET_DUMP
  2  FROM DUAL;


GET_DUMP
------------------------------
test


SQL> SELECT F_GET_FROM_DUMP('74,65,73,74', 'VARCHAR2') GET_DUMP
  2  FROM DUAL;


GET_DUMP
------------------------------
test
.
[/PHP]
编写这个函数所根据的规则来自下列文章:


Oracle基本数据类型存储格式浅析(一)——字符类型:http://blog.itpub.net/post/468/9287

Oracle基本数据类型存储格式浅析(二)——数字类型:http://blog.itpub.net/post/468/9445

Oracle基本数据类型存储格式浅析(三)——日期类型(一):http://blog.itpub.net/post/468/10113

Oracle基本数据类型存储格式浅析(三)——日期类型(二):http://blog.itpub.net/post/468/10293

Oracle基本数据类型存储格式浅析(三)——日期类型(三):http://blog.itpub.net/post/468/10582

Oracle基本数据类型存储格式浅析(三)——日期类型(四):http://blog.itpub.net/post/468/13636

Oracle基本数据类型存储格式浅析(四)——ROWID类型(一):http://blog.itpub.net/post/468/11046

Oracle基本数据类型存储格式浅析(四)——ROWID类型(二):http://blog.itpub.net/post/468/11363

Oracle基本数据类型存储格式浅析(五)——RAW类型:http://blog.itpub.net/post/468/11490


这个函数是由下面这个文章中的包进行修改的:

DBMS_REPAIR的使用(二):http://blog.itpub.net/post/468/13241

使用道具 举报

回复
论坛徽章:
112
2008新春纪念徽章
日期:2008-02-13 12:43:03马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上加薪
日期:2014-02-19 11:55:14马上有车
日期:2014-11-03 12:40:39沸羊羊
日期:2015-03-04 14:43:432015年新春福章
日期:2015-03-06 11:57:31慢羊羊
日期:2015-03-09 16:15:39
39#
发表于 2005-4-10 11:26 | 只看该作者
学习!顶一下

使用道具 举报

回复
论坛徽章:
23
40#
发表于 2005-4-13 15:10 | 只看该作者
十分感谢,用了好长时间看完了。敬佩中。。。。

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表