国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 數(shù)據(jù)庫(kù) > Oracle > 正文

Oracle基本數(shù)據(jù)類(lèi)型存儲(chǔ)格式淺析(二)——數(shù)字類(lèi)型

2024-08-29 13:41:58
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  Oracle的NUMBER類(lèi)型最多由三個(gè)部分構(gòu)成,這三個(gè)部分分別是最高位表示位、數(shù)據(jù)部分、符號(hào)位。其中負(fù)數(shù)包含符號(hào)位,正數(shù)不會(huì)包括符號(hào)位。另外,數(shù)值0比較非凡,它只包含一個(gè)數(shù)值最高位表示位80,沒(méi)有數(shù)據(jù)部分。
  正數(shù)的最高位表示位大于80,負(fù)數(shù)的最高位表示位小于80。其中一個(gè)正數(shù)的最高位是個(gè)位的話,則最高位表示位為C1,百位、萬(wàn)位依次為C2、C3,百分位、萬(wàn)分為依次為C0、BF。一個(gè)負(fù)數(shù)的最高位為個(gè)位的話,最高位表示位為3E,百位、萬(wàn)位依次為3D、3C,百分位、萬(wàn)分位依次為3F、40。
  數(shù)據(jù)部分每一位都表示2位數(shù)。這個(gè)兩位數(shù)可能是從0到99,假如是數(shù)據(jù)本身是正數(shù),則分別用二進(jìn)制的1到64表示,假如數(shù)據(jù)本身是負(fù)數(shù),則使用二進(jìn)制65到2表示。
  符號(hào)位用66表示。
  上面的這些是我通過(guò)DUMP結(jié)果總結(jié)出來(lái)的,對(duì)于上面提到的這些關(guān)系常數(shù),Oracle之所以這樣選擇是有道理的,我們后面根據(jù)例子也可以推導(dǎo)出來(lái),而且會(huì)進(jìn)一步說(shuō)明為什么會(huì)采用這種方式表示。這里列出的意思是使大家先對(duì)NUMBER類(lèi)型數(shù)據(jù)有一個(gè)大概的了解。下面我們通過(guò)一個(gè)例子具體說(shuō)明:
SQL> CREATE TABLE TEST_NUMBER (NUMBER_COL NUMBER);
表已創(chuàng)建。
SQL> INSERT INTO TEST_NUMBER VALUES (0);
已創(chuàng)建 1 行。
SQL> INSERT INTO TEST_NUMBER VALUES (1);
已創(chuàng)建 1 行。
SQL> INSERT INTO TEST_NUMBER VALUES (2);
已創(chuàng)建 1 行。
SQL> INSERT INTO TEST_NUMBER VALUES (25);
已創(chuàng)建 1 行。
SQL> INSERT INTO TEST_NUMBER VALUES (123);
已創(chuàng)建 1 行。
SQL> INSERT INTO TEST_NUMBER VALUES (4100);
已創(chuàng)建 1 行。
SQL> INSERT INTO TEST_NUMBER VALUES (132004078);
已創(chuàng)建 1 行。
SQL> INSERT INTO TEST_NUMBER VALUES (2.01);
已創(chuàng)建 1 行。
SQL> INSERT INTO TEST_NUMBER VALUES (0.3);
已創(chuàng)建 1 行。
SQL> INSERT INTO TEST_NUMBER VALUES (0.00000125);
已創(chuàng)建 1 行。
SQL> INSERT INTO TEST_NUMBER VALUES (115.200003);
已創(chuàng)建 1 行。
SQL> INSERT INTO TEST_NUMBER VALUES (-1);
已創(chuàng)建 1 行。
SQL> INSERT INTO TEST_NUMBER VALUES (-5);
已創(chuàng)建 1 行。
SQL> INSERT INTO TEST_NUMBER VALUES (-20032);
已創(chuàng)建 1 行。
SQL> INSERT INTO TEST_NUMBER VALUES (-234.432);
已創(chuàng)建 1 行。
SQL> COMMIT;
提交完成。
SQL> COL D_NUMBER FORMAT A50
SQL> SELECT NUMBER_COL, DUMP(NUMBER_COL, 16) D_NUMBER FROM TEST_NUMBER;
NUMBER_COL D_NUMBER
---------- --------------------------------------------------
0 Typ=2 Len=1: 80
1 Typ=2 Len=2: c1,2
2 Typ=2 Len=2: c1,3
25 Typ=2 Len=2: c1,1a
123 Typ=2 Len=3: c2,2,18
4100 Typ=2 Len=2: c2,2a
132004078 Typ=2 Len=6: c5,2,21,1,29,4f
2.01 Typ=2 Len=3: c1,3,2
.3 Typ=2 Len=2: c0,1f
.00000125 Typ=2 Len=3: be,2,1a
115.200003 Typ=2 Len=6: c2,2,10,15,1,4
-1 Typ=2 Len=3: 3e,64,66
-5 Typ=2 Len=3: 3e,60,66
-20032 Typ=2 Len=5: 3c,63,65,45,66
-234.432 Typ=2 Len=6: 3d,63,43,3a,51,66
已選擇15行。下面根據(jù)例子得到的結(jié)果,對(duì)每行進(jìn)行說(shuō)明。首先說(shuō)明兩點(diǎn)基本的。DUMP函數(shù)返回的TYPE=2表示DUMP的數(shù)據(jù)類(lèi)型是NUMBER,LENGTH=N表示數(shù)值在數(shù)據(jù)庫(kù)中存儲(chǔ)的長(zhǎng)度是N。

  1.DUMP(0)的結(jié)果是0x80,在前面已經(jīng)提到,0只有高位表示位,沒(méi)有數(shù)據(jù)位。由于0的非凡,既不屬于正數(shù),也不屬于負(fù)數(shù),因此使用高位表示位用80表示就足夠了,不會(huì)和其它數(shù)據(jù)沖突,Oracle出于節(jié)省空間的考慮將后面數(shù)據(jù)部分省掉了。但是為什么Oracle選擇0x80表示0呢?我們知道正數(shù)和負(fù)數(shù)互為相反數(shù),每個(gè)正數(shù)都有一個(gè)對(duì)應(yīng)的負(fù)數(shù)。因此假如我們要使用編碼表示數(shù)值,則表示正數(shù)和負(fù)數(shù)的編碼應(yīng)該各占一半,這樣才能保證使Oracle表示數(shù)據(jù)范圍是合理的。而0x80的二進(jìn)制編碼是1000 0000,正好是一個(gè)字節(jié)編碼最大值的一半,因此,Oracle選擇0x80來(lái)表示0,是十分有道理的。
  2.DUMP(1)的結(jié)果是0xc102,0xc1表示了最高位個(gè)位,0x2表示數(shù)值是1。首先,Oracle為什么用C1表示個(gè)位呢?其實(shí),道理和剛才的差不多。采用科學(xué)計(jì)數(shù)法,任何一個(gè)實(shí)數(shù)S都可以描述為A.B×10n,A表示整數(shù)部分,B表示小數(shù)部分,而N表示10的指數(shù)部分。當(dāng)S大于1時(shí),N大于等于0,S小于1時(shí),N小于0。也就是說(shuō),采用指數(shù)的方式表示,N大于0和N小于0的情況各占一半左右時(shí),Oracle所表示的范圍最廣。因此,Oracle選擇了C1表示個(gè)位是最高位的情況。
SQL> SELECT TO_CHAR(ROUND(TO_NUMBER('81', 'XXX') + (TO_NUMBER('FF', 'XXX') - TO_NUMBER('81', 'XXX') + 1)/2), 'XX') FROM DUAL;  
TO_
---
C1    為什么ORACLE使用0x2表示1,而不直接使用0x1表示1呢?Oracle每個(gè)字節(jié)表示2位數(shù),因此對(duì)于這個(gè)2位數(shù),出現(xiàn)的可能是0~99共100種可能,問(wèn)題出在0這里。Oracle底層是用C語(yǔ)言實(shí)現(xiàn)的,我們知道二進(jìn)制0在C語(yǔ)言中用作字符串終結(jié)符,Oracle為了避免這個(gè)問(wèn)題,因此使用了0x1表示0,并依次類(lèi)推,使用0x64表示99。
  3.DUMP(2)的結(jié)果是0xc103。
  4.DUMP(25)的結(jié)果是0xc11a。前面提到,數(shù)據(jù)部分是以2位為最小單位保存的。因此對(duì)于25來(lái)說(shuō),最高位表示位仍然是個(gè)位,個(gè)位上的值是25,根據(jù)上面推出的規(guī)則,25在存儲(chǔ)為0xc11a。
SQL> SELECT TO_CHAR(25 + 1, 'xx') FROM DUAL;  
TO_
---
1a    5.DUMP(123)的結(jié)果是0xc20218。由于123最高為是百位,所以最高位表示位為0xc2,百位上是1,用0x02表示,個(gè)位上是23,用0x18表示。
  6.DUMP(4100)的結(jié)果是0xc22a。
  注重一點(diǎn),假如數(shù)字最后數(shù)位上假如是0,Oracle出于節(jié)省空間的考慮不會(huì)存儲(chǔ)。比如:4100只保存百位上的41,12000000只保存百位位上的12,512000只保存萬(wàn)位上的51和百位上的20。
  7.DUMP(132004078)的結(jié)果是0xc5022101294f。最高位是億位,因此用0xC5表示,億位上是1用0x02表示,百位位上是32用0x21表示,萬(wàn)位上是0用0x01表示,百位上是40用0x29表示,個(gè)位上78用0x4F表示。
  注重:中間數(shù)位上的0不能省略。
  8.DUMP(2.01)的結(jié)果是0xc10302。最高位是個(gè)位用0xC1表示,個(gè)位上是2用0x03表示,百分位上是1用0x02表示。
  注重:個(gè)位下面一位是百分位不是十分位。
  9.DUMP(0.3)的結(jié)果是0xc01f。最高位是百分位,使用0xC0表示,百分位上是30用0x1F表示。
  10.DUMP(0.00000125)的結(jié)果是0xbe021a。最高位是百萬(wàn)分位,用0xBE表示,最高位上的1用0x02表示,25用0x1a表示。
  11.DUMP(115.200003)的結(jié)果是0xc20210150104。
  12.DUMP(-1)的結(jié)果是0x3e6466。最高位個(gè)位,用0x3E表示,64表示個(gè)位上是1,66是符號(hào)位,表示這個(gè)數(shù)是負(fù)數(shù)。
  負(fù)數(shù)和正數(shù)互為相反數(shù),負(fù)數(shù)的最高位表示位和它對(duì)應(yīng)的相反數(shù)的最高位相加的值是FF。1的最高位表示位是C1,-1的最高位表示位是3E。負(fù)數(shù)中1用64表示。負(fù)數(shù)中的數(shù)值和它相反數(shù)的數(shù)據(jù)相加是0x66,也就是符號(hào)位。正數(shù)1用0x02表示,負(fù)數(shù)1用0x64表示,二者相加是0x66。負(fù)數(shù)多個(gè)一個(gè)標(biāo)識(shí)位,用0x66表示。由于正數(shù)的表示范圍是0x01到0x64,負(fù)數(shù)的表示范圍是0x65到0x02。因此,不會(huì)在表示數(shù)字時(shí)出現(xiàn)的0x66表示。
  13.DUMP(-5)的結(jié)果是0x3e6066。0x3e表示最高位是個(gè)位,0x60表示個(gè)位上是5,0x66是符號(hào)標(biāo)識(shí)位。0x3E加0xC1是0xFF。0x60加0x06的結(jié)果是0x66。
  14.DUMP(-20032)的結(jié)果是0x3c63654566。最高位是萬(wàn)位,正數(shù)的萬(wàn)位是0xC3,因此負(fù)數(shù)的萬(wàn)位是0x3C。萬(wàn)位上是2,正數(shù)用0x03表示,負(fù)數(shù)為0x63,百位上是0,正數(shù)用0x01表示,負(fù)數(shù)使用0x65表示,個(gè)位上是32,正數(shù)用0x21表示,負(fù)數(shù)使用0x45表示。0x66是負(fù)數(shù)表示位。
  15.DUMP(-234.432)的結(jié)果是0x3d63433a5166。    根據(jù)Oracle的存儲(chǔ)特性,還可以推出Oracle的number類(lèi)型的取值范圍。
  Oracle的concept上是這樣描述的:
The following numbers can be stored in a NUMBER column:
Positive numbers in the range 1 x 10^-130 to 9.99...9 x 10^125 with up to 38 significant digits.
Negative numbers from -1 x 10^-130 to 9.99...99 x 10^125 with up to 38 significant digits.
Zero.
  下面來(lái)推導(dǎo)出取值范圍。

來(lái)看符號(hào)位,0xC1表示個(gè)位。
SQL> select to_number('ff', 'xxx') - to_number('c1', 'xxx') from dual;
TO_NUMBER('FF','XXX')-TO_NUMBER('C1','XXX')
-------------------------------------------
62
  由于Oracle是兩位、兩位存儲(chǔ)的,因此最高位相當(dāng)于62×2=124,而且最高位上最大值是99,因此正數(shù)的最大值為9.999……×10^125。
SQL> select to_number('c1', 'xxx') - to_number('80', 'xxx') from dual;
TO_NUMBER('C1','XXX')-TO_NUMBER('80','XXX')
-------------------------------------------
65
  最高位相當(dāng)于65×2=130,因此正數(shù)的最小值為1×10^-130。
  負(fù)數(shù)和正數(shù)在各使用了一半的編碼,因此具有相同的極值范圍。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 留坝县| 池州市| 和田县| 堆龙德庆县| 舒兰市| 文山县| 沈阳市| 凤山市| 长寿区| 惠州市| 平邑县| 高邑县| 班玛县| 桃江县| 韶山市| 稷山县| 巩义市| 长白| 伊春市| 应用必备| 沙田区| 连云港市| 兖州市| 烟台市| 汝南县| 进贤县| 涟水县| 新竹市| 自贡市| 汉川市| 甘泉县| 运城市| 嵩明县| 奉贤区| 静海县| 溧阳市| 新巴尔虎左旗| 白水县| 南郑县| 当阳市| 呼和浩特市|