Decode360's Blog

          業精于勤而荒于嬉 QQ:150355677 MSN:decode360@hotmail.com

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 ::  :: 管理 ::
            397 隨筆 :: 33 文章 :: 29 評論 :: 0 Trackbacks
          從DUMP函數說開去
          ?
          ?
          ??? 因為最近研究字符集,所以對于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:開始進行返回的字符位置
          ??? length:需要返回的字符長度
          ?
          ?
          舉幾個例子:
          ?
          SQL> SELECT DUMP('abc') FROM DUAL;
          ?
          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=UTF8: 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=UTF8]: 61,62,63
          ?
          ??? 1、type
          ?
          ??? 其中typ表示了當前的expr值的類型,例如2表示NUMBER,96表示CHAR等等。
          ??? 具體的所有格式列表在SQL Reference文檔中沒有找到,但是在網上找到了,網址:http://vongates.itpub.net/post/2553/17275
          ?
          CODE TYP
          ----- ------------------------------
          ??? 1 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 TIMEZONE
          ?
          ??? 具體可以從USER_TAB_COLS視圖的定義中獲取這個方法:
          ?
          select text from dba_views where view_name = 'USER_TAB_COLS';
          ?
          ??? 2、Len
          ?
          ??? Len表示該值所占用的字節數。
          ?
          ??? 這個沒有什么好解釋的,但是有時我們也可以使用這個特性發現一些問題,例如:
          ?
          SQL> select value from v$nls_parameters where parameter='NLS_CHARACTERSET';
          ?
          VALUE
          ----------------------------------------------------------------
          UTF8
          ?
          SQL> select dump('多多',1010) from dual;
          ?
          DUMP('多多',1010)
          -------------------------------------------------------
          Typ=96 Len=6 CharacterSet=UTF8: 229,164,154,229,164,154
          ?
          ?
          SQL> conn wxq/wxq@win10gr2
          ?

          SQL> select value from v$nls_parameters where parameter='NLS_CHARACTERSET';
          ?
          VALUE
          ----------------------------------------------------------------
          ZHS16GBK
          ?
          SQL> select dump('多多',1010) from dual;
          ?
          DUMP('多多',1010)
          ---------------------------------------------------
          Typ=96 Len=4 CharacterSet=ZHS16GBK: 182,224,182,224
          ?
          ??? 可以看到,UTF8對于漢字來說,需要3個字節來存儲1個漢字,而我們常用的ZHS16GBK只需要2個字節。
          ?
          ?
          ??? 3、Value
          ?
          ??? 最后就是具體的存儲值了,這里的講究就比較多了,不是幾句話就能夠講得清楚的,更何況我自己就不清楚。恩,簡單得來說,這些返回的數值就是Oracle在自己內部對前面的這個expr值的存儲形式。對于非漢字的普通字符串,可以理解為就是它的ASCII碼(字符集中的編碼值)??梢耘e個例子證明一下:
          ?
          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;
          ?
          CHR(97) CHR(61) CHR(63) CHR(53)
          ------- ------- ------- -------
          a?????? =?????? ??????? 5
          ?
          SQL> SELECT ASCII('a'),ASCII('='),ASCII('?'),ASCII('5') FROM DUAL;
          ?
          ASCII('A') ASCII('=') ASCII('?') ASCII('5')
          ---------- ---------- ---------- ----------
          ??????? 97???????? 61???????? 63???????? 53
          ?
          ??? 而對于漢字的存儲,就不太好測試了,而且也沒有搞清楚原理,應該是直接套用字符集的漢字編碼規則的。
          ?
          ??? 對于數字的存儲,并不像字符那么簡單,而是應用了Oracle自己的一個算法,eygle有過很詳細的說明:
          ??? 具體的算法原理可以參見eygle的這篇文章:http://www.eygle.com/archives/2005/12/how_oracle_stor.html
          ?
          ?
          三、關于其他
          ?
          ??? 順帶介紹一下怎么查找 Oracle對字符集類型的編碼(dump文件的前2個字節):
          ?
          ??? SELECT NLS_CHARSET_NAME(1) FROM DUAL;? --返回數值對應的字符集名稱
          ??? SELECT NLS_CHARSET_ID('US7ASCII') FROM DUAL;? --返回字符集對應的數值
          ?
          ?
          ?
          ?
          ?
          附:dump函數對number的存儲表示
          http://www.eygle.com/archives/2005/12/how_oracle_stor.html
          --------------------------------------------------------------------------------
          How Oracle Store Number internal?
          作者:eygle |English Version 【轉載時請以超鏈接形式標明文章出處和作者信息及本聲明】
          鏈接:
          http://www.eygle.com/archives/2005/12/how_oracle_stor.html
          --------------------------------------------------------------------------------
          Oracle在數據庫內部通過相應的算法轉換來進行數據存儲,本文簡單介紹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;
          DUMP(1100)
          -------------------
          Typ=2 Len=2: 194,12
          ?

          我們會看到,雖然1100>110,但是存儲上1100卻只占2字節,而110卻占了3個字節.
          ?
          ?
          ?
          ?
          posted on 2009-06-17 23:08 decode360 閱讀(953) 評論(0)  編輯  收藏 所屬分類: 07.Oracle
          主站蜘蛛池模板: 怀远县| 双江| 河津市| 五河县| 平度市| 万载县| 瑞丽市| 彭水| 大悟县| 左贡县| 南投县| 宁陵县| 班戈县| 金昌市| 三门县| 宝清县| 双辽市| 孙吴县| 鹿泉市| 苗栗市| 宕昌县| 蓝田县| 渝北区| 修水县| 宁武县| 九寨沟县| 仁寿县| 莆田市| 陆良县| 石首市| 平乡县| 西峡县| 玛曲县| 普陀区| 景宁| 河曲县| 溧阳市| 通山县| 建水县| 贵南县| 平谷区|