zoukankan      html  css  js  c++  java
  • 利用dump函数理解oracle如何存储各种类型数据

    1.dump函数介绍

    1.1标准格式

    DUMP(expr[,return_fmt[,start_position][,length]])

    expr:需要dump的表达式

    return_fmt:指返回参数的格式,有5种用法:

              1)8:以8进制返回结果的值

              2)10:以10进制返回结果的值(默认)

              3)16:以16进制返回结果的值

              4)17:以单字符的形式返回结果的值

              5)1000:以上4种加上1000,表示在返回值中加上当前字符集

    start_position:需要返回的起始字符位置

    length:需要返回的字符长度

    1.2 返回结果

    返回结果包含三方面值,分别是TYPE、LEN、VALUE,例如

    1 DUMP('ABC')
    2 ----------------------
    3 Typ=96 Len=3: 97,98,99

    其一,typ表示当前的expr值的类型,有如下类型

     1 CODE TYP
     2 ----- ------------------------------
     3 1     VARCHAR2
     4 2     NUMBER
     5 8     LONG
     6 12    DATE
     7 23    RAW
     8 24    LONG RAW
     9 69    ROWID
    10 96    CHAR
    11 112   CLOB
    12 113   BLOB
    13 114   BFILE
    14 180   TIMESTAMP
    15 181   TIMESTAMP WITH TIMEZONE
    16 182   INTERVAL YEAR TO MONTH
    17 183   INTERVAL DAY TO SECOND
    18 208   UROWID
    19 231   TIMESTAMP WITH LOCAL TIMEZONE

    其二,len表示该值所占用的字节数

    其三,value部分即为oracle在内部如何来存储这个expr值

    2.几种常用数据类型的dump

    2.1Date类型

    1 SYS@crm AS SYSDBA>col DUMP_DATE format a50
    2 SYS@crm AS SYSDBA>select dump(last_ddl_time) dump_date, to_char(last_ddl_time,'yyyy-mm-dd hh24:mi:ss') real_date from user_objects where rownum=1;
    3 
    4 DUMP_DATE                                          REAL_DATE
    5 -------------------------------------------------- -------------------
    6 Typ=12 Len=7: 120,112,5,21,21,33,9                 2012-05-21 20:32:08
    7 
    8 Elapsed: 00:00:00.01

    Oracle是按如下表格所示来存储date类型数据的,根据dump值做相应的逆行运算即可.

    世纪

    120 - 100 = 20

    世纪和年份加100后存储

    年份

    112 - 100 = 12

    月份

    5

    月份和日期按原值存储

    日期

    21

    小时

    21 - 1 = 20

    时间均加1后存储

    分钟

    33 - 1 = 32

    9 - 1 = 8

    留意了一下内存中date类型数据的表示,果然还是不一样。

    1 SYS@crm AS SYSDBA>col dumpsysdate format a50
    2 SYS@crm AS SYSDBA>select dump(sysdate) dumpsysdate, sysdate from dual;
    3 
    4 DUMPSYSDATE                                        SYSDATE
    5 -------------------------------------------------- -------------------
    6 Typ=13 Len=8: 221,7,7,29,12,5,25,0                 2013-07-29 12:05:25

    这里有几个需要注意的:typ变成了13,这在上面列举的数据类型表里貌似没有。看的出来,除了世纪和年份,其它值和真实值都一模一样;那这里的2013是怎么运算得出221,7的呢?

    因为这个机器是little-endian architecture的服务器,“221,7”应该解读为“7,221”,两个数字分别换算成十六进制后合起来就是“0x7DD”,即2013,这就对上了!

     1 SYS@crm AS SYSDBA>select to_char(221,'xxx') from dual;
     2 TO_C
     3 ----
     4   dd
     5 Elapsed: 00:00:00.00
     6 
     7 SYS@crm AS SYSDBA>select to_number('7DD','XXX') FROM DUAL;
     8 TO_NUMBER('7DD','XXX')
     9 ----------------------
    10                   2013

    2.2 Number类型

    Number类型dump出来有点特别,value方面里第一个数字(用value1来表示)代表符号位/指数,按以下方法来计算

    正数:指数=value1 - 193 (value1换算成二进制后最高位为1则代表正数) 
    负数:指数=62 - value1(value1换算成二进制后最高位为0则代表负数)

    从value2开始,正数加1存储;负数被101减后存储,并且如果总长度小于21个字节,为了排序的需要,最后加一个102。

    所存储的数值计算方法为:

    把下面计算的结果加起来:

    每个数字乘以100^(指数-N) (N是有效位数的顺序位,第一个有效位的N=0)

    例:

    1 select dump(123456.789) from dual;
    2 DUMP(123456.789)
    3 -------------------------------
    4 Typ=2 Len=6: 195,13,35,57,79,91

    Value1(指数)

    195 - 193 = 2

    Value2

    13 - 1 = 12

    *1002-0

    120000

    Value3

    35 - 1 = 34

    *1002-1

    3400

    Value4

    57 - 1 = 56

    *1002-2

    56

    Value5

    79 - 1 = 78

    *1002-3

    .78

    Value6

    91 - 1 = 90

    *1002-4

    .009

     

    123456.789

    1 select dump(-123456.789) from dual;
    2 DUMP(-123456.789)
    3 ----------------------------------
    4 Typ=2 Len=7: 60,89,67,45,23,11,102

    Value1(指数)

    62 - 60 = 2

    Value2

    101 - 89 = 12

    *1002-0

    120000

    Value3

    101 - 67 = 34

    *1002-1

    3400

    Value4

    101 - 45 = 56

    *1002-2

    56

    Value5

    101 - 23 = 78

    *1002-3

    .78

    Value6

    101 - 11 = 90

    *1002-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的情况

    2.3charvarchar2类型

    英文字符的dump值可以直接理解为对应的ASCII码。

    1 SYS@crm AS SYSDBA>select dump('abcdefg') from dual;
    2 DUMP('ABCDEFG')
    3 --------------------------------------
    4 Typ=96 Len=7: 97,98,99,100,101,102,103

    中文字符的dump值则要看具体的字符集了。

     1 SYS@crm AS SYSDBA>select dump('笑看风云') from dual;
     2 DUMP('笑看风云')
     3 --------------------------------------------------------------
     4 Typ=96 Len=12: 231,172,145,231,156,139,233,163,142,228,186,145
     5 Elapsed: 00:00:00.00
    6 SYS@crm AS SYSDBA>select dump('笑看风云',1010) from dual; 7 DUMP('笑看风云',1010) 8 ------------------------------------------------------------------------------------ 9 Typ=96 Len=12 CharacterSet=AL32UTF8: 231,172,145,231,156,139,233,163,142,228,186,145 10 Elapsed: 00:00:00.00

    下面看看char varchar2两种类型数据的存储的区别。

     1 SYS@crm AS SYSDBA>create table zjtest(c1 varchar2(10),c2 char(10));
     2 Table created.
     3 Elapsed: 00:00:00.11
     4 
     5 SYS@crm AS SYSDBA>insert into zjtest values (1,1);
     6 1 row created.
     7 Elapsed: 00:00:00.00
     8 
     9 SYS@crm AS SYSDBA>insert into zjtest values (2,2);
    10 1 row created.
    11 Elapsed: 00:00:00.00
    12 
    13 SYS@crm AS SYSDBA>insert into zjtest values (3,3);
    14 1 row created.
    15 Elapsed: 00:00:00.00
    16 SYS@crm AS SYSDBA>commit;
    17 SYS@crm AS SYSDBA>col DUMP(C1) format a50
    18 SYS@crm AS SYSDBA>col DUMP(C2) format a50
    19 SYS@crm AS SYSDBA>select c1,dump(c1),c2,dump(c2) from zjtest;
    20 
    21 C1         DUMP(C1)                                           C2         DUMP(C2)
    22 ---------- -------------------------------------------------- ---------- --------------------------------------------------
    23 1          Typ=1 Len=1: 49                                    1          Typ=96 Len=10: 49,32,32,32,32,32,32,32,32,32
    24 2          Typ=1 Len=1: 50                                    2          Typ=96 Len=10: 50,32,32,32,32,32,32,32,32,32
    25 3          Typ=1 Len=1: 51                                    3          Typ=96 Len=10: 51,32,32,32,32,32,32,32,32,32
    26 
    27 Elapsed: 00:00:00.00

    两者的区别一览无余。

    注:本文部分内容引用自eygle博客http://www.eygle.com/archives/2005/12/how_oracle_stor.html

  • 相关阅读:
    Chrome 使用 Evernote 插件
    【MySQL】ON DUPLICATE KEY UPDATE
    【MySQL】Illegal mix of collations (utf8mb4_general_ci,IMPLICIT) and ...
    libevent API
    LLServer--》对LevelDB的应用
    Linux信号signal处理机制
    守护进程
    使用 libevent 和 libev 提高网络应用性能(IBM)
    Libev和LibEvent
    利用TokyoTyrant构建兼容Memcached协议、支持故障转移、高并发的分布式Key-value持久存储系统(转)
  • 原文地址:https://www.cnblogs.com/leonora/p/3223296.html
Copyright © 2011-2022 走看看