oracle數(shù)值類型漫談

這片博客本來想的是只寫pls_integer與number之間的性能比較,但是提筆之后我又想寫更多我的思考過程,于是索性寫一篇關于oracle數(shù)值類型的文章。干貨太多,未免看得乏味,本篇我嘗試用一種聊天談話的方式行文,希望同行者可以在一種輕松的氛圍中和我一起來探討oracle的諸多數(shù)值類型,好吧,那我就先拋磚引玉了。
1、number
我最先接觸的數(shù)值類型就是老大哥number,它定義為number(p,s),p是精度,最大38位,s是刻度范圍,可在-84~127間取值。舉個栗子(例子):number(4,2),指的就是小數(shù)點整數(shù)+小數(shù)部分一共有4位,不包含小數(shù)點位,也就是說整數(shù)部分最多兩位,如果小數(shù)部分多于2位,會做四舍五入處理(對于sqlserver和MySQL也會做四舍五入處理),如果小數(shù)部分不足2位的話,則會補0(對于sqlserver也會補0,但是mysql不會),如果不寫p,s,那么就默認為38。number類型是oracle最常用的數(shù)字類型了,在很長一段時間之內(nèi),我以為數(shù)值類型就只有number,因為number類型足以處理幾乎全部的數(shù)字類型了。但是之后在oracle道路上繼續(xù)行走的過程中,我又認識了其他衍生的數(shù)值類型。
2、integer
其實最開始看到這個數(shù)值類型的時候,同很多人一樣,我也認為它是number類型的子類型,最大38位,對于小數(shù)做自動四舍五入處理,但是后來我發(fā)現(xiàn)不完全是這樣的。作為number的子類型不假,一般情況下,integer是作為存儲整數(shù)值存在的,在需要存儲整數(shù)值的時候我們會想到這個數(shù)值類型,但是它的最大位可不是38位,在插入的測試數(shù)值看到,它已經(jīng)遠遠超過38位了,如圖:
oracle數(shù)值類型漫談
可以看到,對于integer只能存儲38位的言論可謂是直接推翻。接下來我們來看坊間盛傳的,"integer只能存儲整數(shù),對于小數(shù)會做四舍五入處理",來看一個例子:
create or replace procedure integer_test(a integer)
as 
b integer := a;
begin
  dbms_output.put_line(b);
end;
輸出結果如圖:
oracle數(shù)值類型漫談
看到這個結果的時候,相信很多同學都已經(jīng)涼了,簡直是顛覆了以往的認識啊,的確,從這個例子可以看出,integer是number的子類型,但是它不會強制進行四舍五入處理,同時它最大位數(shù)大于38位。
3、int,numeric,decimal
這三種數(shù)值類型是oracle為了兼容其他數(shù)據(jù)庫而存在的,同樣都是number的子類型。在進行類型聲明的時候,如果直接聲明為int,numeric,decimal,它會被直接存為integer,處理方式同integer一模一樣;numeric和decimal如果帶有精度和刻度范圍,那么會被存為number(p,s),處理方式同number(p,s),int類型只能被聲明為int,不能帶精度和刻度范圍,所以只能當作integer來處理。
4、float
float也是number的子類型,float(n),n指的是精度,是二進制精度,這里可不是十進制精度哦,計算公式為:binary precision=ceil(b*0.30103),float沒有刻度范圍.n的范圍為1~126。那么怎么計算存入數(shù)據(jù)庫中的數(shù)值呢,比如:float(2),那么它的精度是ceil(2*0.30103)=1,如果存入13.5,那么應該是1.35*10^1,精度為1,1.35四舍五入變?yōu)?,所以就是1*10^1=10存入的結果就是10;如果是19.5,那么應該是1.95*10^1,精度為1,1.95四舍五入為2,就是2*10^1,結果存入20。如果沒有精度,那么映射為number類型,直接存入此值。oracle沒有直接為double類型的數(shù)值類型。
5、binary_integer和pls_integer
這個數(shù)字類型只能用于PL/SQL,他們相比number來說更具優(yōu)勢,首先是占有較少的存儲空間,其次他們是直接通過硬件來計算的,也就是直接通過CPU進行計算,而不用經(jīng)過轉換,number類型在計算的時候,還要先被轉換為二進制,所以在計算速度上,binary_integer和pls_integer比number性能好很多,建議在PL/SQL中使用這兩種數(shù)據(jù)類型來代替number,你將會得到很大的驚喜。
5、binary_float和binary_double
這兩種數(shù)值類型10g之后才出現(xiàn),binary_float可以存儲一個單精度的32位浮點數(shù),binary_double可以存儲一個雙精度的64位浮點數(shù),binary_float和binary_double占有更少的存儲空間,同樣的,binary_float和binary_double也是直接通過硬件計算的,所以它的計算效率更高,而且它們比起number來說可以存儲更大或者更小的數(shù)值,但是這兩種數(shù)值類型也會存在精度不準的情況。
6、寫到浮點型,我需要說一說浮點型存數(shù)不精確的原因:
首先,我們要知道浮點型在計算機是怎么存儲的,比如:要存入13.75,首先將整數(shù)部分轉為二進制,13轉為二進制是1101,接下來將小數(shù)部分轉為二進制,小數(shù)部分是0.75,將小數(shù)部分乘以2,取結果的整數(shù)部分為二進制的一位,然后繼續(xù)取結果的小數(shù)部分乘以2重復,一直到小數(shù)部分全部為0結束,在這個過程中,是會出現(xiàn)循環(huán)乘不盡的情況,但是因為浮點數(shù)的小數(shù)位是確定的(float是23位,double是52位),所以到了指定的小數(shù)位就會停下來,這就是浮點數(shù)存數(shù)不精確的原因,可以看到如果可以在小數(shù)位范圍之內(nèi)乘盡的話,那么結果就存儲的準確了。來看看小數(shù)部分(0.75)轉為二進制的過程:
0.75*2=1.5   取1
0.5*2=1     取1
乘到這里,即0.5*2=1,1已經(jīng)沒有小數(shù)部分了,所以到這里也就停止了,最后的結果是0.11,與上面整數(shù)部分合起來,那么13.75轉換為二進制為1101.11,即1.10111*2^3,1.10111是小數(shù)部分,2為底,6為指數(shù)部分,這個1.10111*2^3就是轉換好的二進制浮點數(shù),接著就是將這個二進制浮點數(shù)存入計算機了。
將其存入計算機內(nèi),將會使用浮點表示法,分為三大部分:
第一部分:符號位,占用1位,用來區(qū)分正負數(shù),0為正數(shù),1為負數(shù);對于1.10111*2^3,它是正數(shù),所以符號位是0
第二部分:指數(shù)位,float占用8位,double占用11位,用來表示指數(shù);對于1.10111*2^3,指數(shù)位是3
第三部分:小數(shù)位,float占用23位,double占用52位,用來表示小數(shù),不足位數(shù)補0;對于1.10111*2^3,小數(shù)位是10111
所以對于float,符號位+指數(shù)位+小數(shù)位=1+8+23=32位,對于double,符號位+指數(shù)位+小數(shù)位=64位,同時可以看到,指數(shù)位決定了大小范圍,小數(shù)位決定了精度。因為指數(shù)位有可能是正數(shù),也有可能是負數(shù),負數(shù)算起來比正數(shù)麻煩,所以為了減少計算的麻煩,在存儲指數(shù)的時候,需要將它存儲位無符號的整數(shù),所以在指數(shù)位上會加一個偏移量,float的偏移量是127,double的偏移量是1023,如果需要轉換為十進制的話,到時候指數(shù)減去相應的值就可以了。那么對于13.75(float),本來它的二進制指數(shù)值是3,現(xiàn)在就成了3+127=130,轉換為二進制是10000010,最終:13.75(float)被存儲為:符號位 指數(shù)位 小數(shù)位(不足位補0)=0 10000010 10111 00000 00000 00000 000
7、萬丈高樓平地起,有時候我們太過追求一些高級語法,或者高大尚的東西,反而在基礎的東西上掌握不牢,實際上,數(shù)據(jù)庫的基礎數(shù)據(jù)類型往往沒有表面上看的那么簡單,其實任何語言都是一樣,只有掌握好基礎知識,做一個基礎精通者,那么,在我們進階的道路上就會水到渠成。寫到最后,才發(fā)現(xiàn)整體下來,整篇文章也沒有那么輕松,嚴肅的東西寫慣了,一下子不太適應寫輕松的東西,沒事,能拋磚引玉就好。
oracle數(shù)值類型漫談


當前題目:oracle數(shù)值類型漫談
轉載源于:http://muchs.cn/article32/gecdpc.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供小程序開發(fā)、Google網(wǎng)站營銷、網(wǎng)站收錄、網(wǎng)站改版、App設計

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運營