转--Oracle数据类型及存储方式【C】
生活随笔
收集整理的這篇文章主要介紹了
转--Oracle数据类型及存储方式【C】
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
第二部分 數(shù)值類型
§ 2.1? number
Number類型是oralce的數(shù)值類型,存儲(chǔ)的數(shù)值的精度可以達(dá)到38位。Number是一種變長(zhǎng)類型,長(zhǎng)度為0-22字節(jié)。取值范圍為:10e-130 – 10e 126(不包括)
Number(p,s)
P和s都是可選的。
P指精度(precision),即總位數(shù)。默認(rèn)情況下精度為38。精度的取值范圍為1~38.
S指小數(shù)位(scale).小數(shù)點(diǎn)右邊的位數(shù)。小數(shù)點(diǎn)位數(shù)的合法值為-48~127。小數(shù)位的默認(rèn)值由精度來決定。如果沒有指定精度,小數(shù)位默認(rèn)為最大的取值區(qū)間.如果指定了精度,沒有指定小數(shù)位。小數(shù)位默認(rèn)為0(即沒有小數(shù)位).
精度和小數(shù)位不會(huì)影響數(shù)據(jù)如何存儲(chǔ),只會(huì)影響允許哪些數(shù)值及數(shù)值如何舍入。
1.新建一個(gè)表
SQL> create table test_number(col_number number(6,2));
Table created
2.插入一些不同的數(shù)據(jù)
SQL> insert into test_number values(-1);
1 row inserted
SQL> insert into test_number values(0);
1 row inserted
SQL> insert into test_number values(1);
1 row inserted
SQL> insert into test_number values(2);
1 row inserted
SQL> insert into test_number values(11.00);
1 row inserted
SQL> insert into test_number values(11.11);
1 row inserted
SQL> insert into test_number values(1234.12);
1 row inserted
SQL> insert into test_number values(-0.1);
1 row inserted
SQL> insert into test_number values(-11.11);
1 row inserted
SQL> insert into test_number values(-1234.12);
1 row inserted
SQL> commit;
Commit complete
3.查看結(jié)果
SQL> select * from test_number;
COL_NUMBER
----------
???? -1.00
????? 0.00
????? 1.00
????? 2.00
???? 11.00
???? 11.11
?? 1234.12
???? -0.10
??? -11.11
? -1234.12
10 rows selected
5. 查看存儲(chǔ)結(jié)構(gòu)
SQL> select col_number, dump(col_number) from test_number;
COL_NUMBER DUMP(COL_NUMBER)
---------- --------------------------------------------------------------------------------
???? -1.00 Typ=2 Len=3: 62,100,102
????? 0.00 Typ=2 Len=1: 128
????? 1.00 Typ=2 Len=2: 193,2
????? 2.00 Typ=2 Len=2: 193,3
???? 11.00 Typ=2 Len=2: 193,12
???? 11.11 Typ=2 Len=3: 193,12,12
?? 1234.12 Typ=2 Len=4: 194,13,35,13
???? -0.10 Typ=2 Len=3: 63,91,102
??? -11.11 Typ=2 Len=4: 62,90,90,102
? -1234.12 Typ=2 Len=5: 61,89,67,89,102
10 rows selected
由此可見:
Number類型的內(nèi)部編碼為:2
根據(jù)每一行的len值可以看出,number是一個(gè)變長(zhǎng)類型。不同的數(shù)值占用不同的空間。
如果指定了精度,顯示結(jié)果與精度相關(guān)。
就像我插入語句寫為
insert into test_number values(0);
但是顯示結(jié)果為:0.00
如果數(shù)值是負(fù)數(shù),在最后一位上填充一個(gè)補(bǔ)碼102.即表示該數(shù)值為負(fù)數(shù)。
0是一個(gè)特殊的值,它在oracle中存儲(chǔ)為128.
第一位為標(biāo)志位。以128為比較。如果數(shù)值大于128,則它大于0。如果小于128小于0。
-1的內(nèi)部存儲(chǔ)為:
-1.00 Typ=2 Len=3: 62,100,102
最后一位是102,是一個(gè)負(fù)數(shù)。
第一位小于128,所以小于10.
除了第一位標(biāo)志位外,其它的都是數(shù)值為了。
如果該值是一個(gè)正數(shù)。每一位的存儲(chǔ)值減1為每一位的實(shí)際值。
1.0的存儲(chǔ)結(jié)構(gòu)為:
1.00 typ=2 Len=2: 193,2
實(shí)值上1.00的存儲(chǔ)結(jié)果與1相同。
第一位193為標(biāo)志位,大于128,大于0.
第二位為數(shù)值為,因?yàn)槭钦龜?shù),實(shí)際值為存儲(chǔ)值減1。2-1 = 1。
如是該值是一個(gè)負(fù)數(shù),每一位的實(shí)際值為101 減去存儲(chǔ)的值。
-1.00的存儲(chǔ)結(jié)構(gòu)為:
-1.00 Typ=2 Len=3: 62,100,102
最后一位102為補(bǔ)位。
第一位62為標(biāo)志位,小于128。實(shí)際值小于0.
第二位為數(shù)值為,因?yàn)槭秦?fù)數(shù)。實(shí)際值為:101 – 100? =1.
§2.2 小數(shù)位在哪里?
從上面的存儲(chǔ)結(jié)果看,對(duì)小數(shù)存儲(chǔ)時(shí),它并沒有一個(gè)小數(shù)的標(biāo)志位。但是它實(shí)際上是由第一位標(biāo)志位,和數(shù)值位(第二位)來決定的。
當(dāng)存儲(chǔ)的數(shù)是一個(gè)正數(shù),該數(shù)值的前幾位為:第一位 * power(100 , (標(biāo)志位 - 193));
當(dāng)存儲(chǔ)的數(shù)是一個(gè)負(fù)數(shù),該數(shù)值的前幾位為:第一位 * power(100,(62 – 標(biāo)志位));
11.11的存儲(chǔ)結(jié)果為:
11.11 Typ=2 Len=3: 193,12,12
第一位數(shù)值位為:12 實(shí)際數(shù)值為11
標(biāo)志位為:193
12 * power(100, (193- 193);
?? 100的零次方為1.
12 乘1 等于12.
所以這個(gè)數(shù)的前幾位為:12。從這后面就是小數(shù)了。
1234.12的存儲(chǔ)結(jié)構(gòu)為:
1234.12 Typ=2 Len=4: 194,13,35,13
第一位數(shù)值位為:13,實(shí)際值為12
標(biāo)志位為:193
13 * power(100,(194-193)) = 1300
所以前四位為整數(shù)位,后面的為小數(shù)位。
-0.10的存儲(chǔ)結(jié)構(gòu)為:
-0.10 Typ=2 Len=3: 63,91,102
標(biāo)志位為:63
第一位數(shù)值為:91 ,實(shí)際值為:10
91 * (100,(62-63)) =-9100.
所以小數(shù)位在91之前。
-1234.12的存儲(chǔ)結(jié)構(gòu)為:
-1234.12 Typ=2 Len=5: 61,89,67,89,102
標(biāo)志位為:61
第一位數(shù)值為:89
89*(100,(62-61)) =8900
所以小數(shù)位在67之后。
§2.3 number的精度和小數(shù)位
Number類型的精度最多可是38位。小數(shù)位-84--127位。
SQL> create table test_number1(col_number number(39));
create table test_number1(col_number number(39))
ORA-01727: numeric precision specifier is out of range (1 to 38)
指定小數(shù)位時(shí),精度只能是1-38。不能是0
SQL> create table test_number1(col_number number(0,127));
create table test_number1(col_number number(0,127))
ORA-01727: numeric precision specifier is out of range (1 to 38)
SQL> create table test_number1(col_number number(1,128));
create table test_number1(col_number number(1,128))
ORA-01728: numeric scale specifier is out of range (-84 to 127)
精度與小數(shù)位的關(guān)系。精度并不是小數(shù)位加整數(shù)位之和。
我們先看看小數(shù)位為0的情況。
SQL> create table test_number1(col_char varchar2(200), col_num number(10));
Table created
Number(10).只定義了精度,小數(shù)位為0.
看看它可以存放的數(shù)據(jù)。
SQL> insert into test_number1 values('9999999999',9999999999);
1 row inserted
插入了10個(gè)9,沒有問題,再插入多一位看看
SQL> insert into test_number1 values('99999999991',99999999991);
insert into test_number1 values('99999999991',99999999991)
ORA-01438: value larger than specified precision allowed for this column
報(bào)錯(cuò)了,精度不夠。
再看看能不能再插入小數(shù)?
SQL> insert into test_number1 values('0.9',0.9);
1 row inserted
SQL> select * from test_number1;
Col_char COL_NUM
-------------------- --------------
9999999999 9999999999
0.9 ???????????? 1
注意插入數(shù)值0.9后,存儲(chǔ)為1.這就是小數(shù)位的作用。在哪里進(jìn)行舍入。
帶小數(shù)位和精度的情況。
SQL> create table test_number2(col_char varchar(20),col_num number(1,3));
Table created
精度是1,小數(shù)位是3.
可見,精度不是小數(shù)位加整數(shù)位了。但是精度和小數(shù)位倒底什么關(guān)系呢?
SQL> insert into test_number2 values('0.111',0.111);
insert into test_number2 values('0.111',0.111)
ORA-01438: value larger than specified precision allowed for this column
插入3位小數(shù),0.111竟然報(bào)錯(cuò)了,說精度不夠。
SQL> insert into test_number2 values('0.001',0.001);
1 row inserted
插入0.001時(shí),成功了。
SQL> insert into test_number2 values('0.001',0.0015);
1 row inserted
插入0.0015也成功了。
看看插入的值。
SQL> select * from test_number2;
COL_CHAR???????????? COL_NUM
-------------------- -------
0.001????????????????? 0.001
0.0015???????????????? 0.002
需要注意的是0.0015被舍入為0.002
精度大于小數(shù)位
SQL> create table test_number3 (col_char varchar(20), col_number number(5,3));
Table created
SQL> insert into test_number3 values('99.899',99.899);
1 row inserted
SQL> insert into test_number3 values('99.999',99.999);
1 row inserted
SQL> insert into test_number3 values('99.9999',99.9999);
insert into test_number3 values('99.9999',99.9999)
ORA-01438: value larger than specified precision allowed for this column
注意,當(dāng)插入99.9999時(shí),系統(tǒng)報(bào)錯(cuò)。因?yàn)樾?shù)位為3位。第四位小數(shù)位是9,于是往前入。最終變成100.000.就已經(jīng)超過了精度。
Number(5,3)可存儲(chǔ)的數(shù)值最大為99.999.
現(xiàn)在終于有點(diǎn)明白小數(shù)位與精度的關(guān)系了。
number(38,127)
可以存儲(chǔ)的最大小數(shù)為:127位小數(shù),最后38為9.
即:0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000099999999999999999999999999999999999999
小數(shù)位為負(fù)數(shù)。
我們從前面知道,小數(shù)位的取值為-48 ~127
為什么小數(shù)位會(huì)為負(fù)數(shù)?這有點(diǎn)怪異了。像上面的number(5,3)將值舍入為最接近0.001
Number(5,-3)就是將值舍入為最接近的1000
SQL> create table test_number5 (col_char varchar(20), col_num number(5,-3));
Table created
插入值10999
SQL> insert into test_number5 values('10999',10999);
1 row inserted
查看一下結(jié)果
SQL> select * from test_number5;
COL_CHAR???????????? COL_NUM
-------------------- -------
10999????????????????? 11000
存儲(chǔ)的結(jié)果為:11000
當(dāng)小數(shù)部分為負(fù)數(shù)時(shí),是對(duì)小數(shù)部分進(jìn)行舍入。
那么精度在這時(shí)起到什么作用呢?與小數(shù)位又有什么關(guān)系?
SQL> insert into test_number5 values('111111111',111111111);
insert into test_number5 values('111111111',111111111)
ORA-01438: value larger than specified precision allowed for this column
插入9個(gè)1時(shí),報(bào)錯(cuò)精度不夠。
SQL> insert into test_number5 values('11111111',11111111);
1 row inserted
插入8個(gè)1時(shí),正確插入。
我們看看它的結(jié)果,看它是怎么舍入的。
SQL> select * from test_number5;
COL_CHAR???????????? COL_NUM
-------------------- -------
11111111???????????? 11111000
結(jié)果是1111100而不是1111100
無限接近1000,就是從百位開始進(jìn)行四舍五入,后面的值全部為0。
所以看出number(5,-3)可存儲(chǔ)的最大值為:99999000
SQL> insert into test_number5 values('99999499.999999',99999499.999999);
1 row inserted
SQL> select * from test_number5;
COL_CHAR???????????? COL_NUM
-------------------- -------
99999999???????????? 99999000
99999499.999999????? 99999000
現(xiàn)在應(yīng)該明白了精度和小數(shù)位的關(guān)系了吧。
小數(shù)位告訴系統(tǒng)保留多少位小數(shù),從哪里開始舍入。
精度舍入后,從舍入的位置開始,數(shù)值中允許有多少位。
§2.4? binary_float 和binary_double
這兩種類型是oracle 10g新引進(jìn)的數(shù)值類型。在oracle 10g之前是沒有這兩種類型的。
Number類型是由oracle軟件支持的類型。而浮點(diǎn)數(shù)用于近似數(shù)值。但是它浮點(diǎn)數(shù)允許由在硬盤上(CPU,芯片)上執(zhí)行運(yùn)行。而不是在oracel進(jìn)程中運(yùn)算。如果希望在一個(gè)科學(xué)計(jì)算中執(zhí)行實(shí)數(shù)處理,依賴于硬件的算術(shù)運(yùn)算速度要快得多。但是它的精度卻很小。如果希望用來存儲(chǔ)金融數(shù)值,則必須用number.
BINARY_FLOAT是一種IEEE固有的單精度浮點(diǎn)數(shù)。可存儲(chǔ)6位精度,取值范圍在~±1038.25的數(shù)值。
BINARY_DOUBLE是一種IEEE固有的雙精度浮點(diǎn)數(shù)。可存儲(chǔ)12位精度。取值范圍在~±10308.25的數(shù)值
SQL> create table test_floatdouble(col_number number, col_float binary_float, col_double binary_double);
Table created
SQL> insert into test_floatdouble values(9876543210.0123456789,9876543210.0123456789,9876543210.0123456789);
1 row inserted
2 SQL> select to_char(col_number), to_char(col_float), to_char(col_double) from test_floatdouble;
3
4 TO_CHAR(COL_NUMBER)????????????????????? TO_CHAR(COL_FLOAT)?????????????????????? TO_CHAR(COL_DOUBLE)
5 ---------------------------------------- ---------------------------------------- ----------------------------------------
6 9876543210.0123456789??????????????????? 9.87654349E+009????????????????????????? 9.8765432100123463E+009
由此可見,binary_float無法表示這個(gè)數(shù)。Binary_float和binary_double無法用于對(duì)精度要求高的數(shù)據(jù)。
SQL> select dump(col_float)from test_floatdouble;
DUMP(COL_FLOAT)
--------------------------------------------------------------------------------
Typ=100 Len=4: 208,19,44,6
BINARY_FLOAT 類型編碼為100
Len=4 占用4個(gè)字節(jié)。它是采用固定字節(jié)進(jìn)行存儲(chǔ)的。
SQL> select dump(col_double)from test_floatdouble;
DUMP(COL_DOUBLE)
--------------------------------------------------------------------------------
Typ=101 Len=8: 194,2,101,128,183,80,25,73
BINARY_DOUBLE 類型編碼為101
Leng= 8 占用8個(gè)字節(jié)。也是采用固定字節(jié)進(jìn)行存儲(chǔ)。
注意:number 類型使用的CPU時(shí)間是浮點(diǎn)數(shù)類型的50倍。浮點(diǎn)數(shù)是數(shù)值的一個(gè)近似值,精度在6-12位之間。從Number類型得到的結(jié)果要比從浮點(diǎn)數(shù)得到的結(jié)果更精確。但在對(duì)科學(xué)數(shù)據(jù)進(jìn)行數(shù)據(jù)挖掘和進(jìn)行復(fù)雜數(shù)值分析時(shí),精度的損失是可以接受的,還會(huì)帶來顯著的性能提升。
這時(shí)需要使用內(nèi)置CAST函數(shù),對(duì)NUMBER類型執(zhí)行一種實(shí)時(shí)的轉(zhuǎn)換,在執(zhí)行復(fù)雜數(shù)學(xué)運(yùn)算之前先將其轉(zhuǎn)換為一種浮點(diǎn)數(shù)類型。CPU使用時(shí)間就與固有浮點(diǎn)類型使用的CPU時(shí)間非常接近了。
Select ln(cast(number_col as binary_double)) from test_number.
§2.5 Oracle在語法上還支持的數(shù)值數(shù)據(jù)類型
NUMERIC(p,s):完全映射到NUMBER(p,s)。如果p未指定,則默認(rèn)為38.
DECIMAL(p,s)或DEC(p,s):同NUMERIC(p,s).
INTEGER或int:完全映射至NUMBER(38)
SMALLINT:完全映射至NUMBER(38)
FLOAT(b):映射至NUMBER
DOUBLE PRECISION:映射到NUMBER
REAL:映射到NUMBER.
§ 2.1? number
Number類型是oralce的數(shù)值類型,存儲(chǔ)的數(shù)值的精度可以達(dá)到38位。Number是一種變長(zhǎng)類型,長(zhǎng)度為0-22字節(jié)。取值范圍為:10e-130 – 10e 126(不包括)
Number(p,s)
P和s都是可選的。
P指精度(precision),即總位數(shù)。默認(rèn)情況下精度為38。精度的取值范圍為1~38.
S指小數(shù)位(scale).小數(shù)點(diǎn)右邊的位數(shù)。小數(shù)點(diǎn)位數(shù)的合法值為-48~127。小數(shù)位的默認(rèn)值由精度來決定。如果沒有指定精度,小數(shù)位默認(rèn)為最大的取值區(qū)間.如果指定了精度,沒有指定小數(shù)位。小數(shù)位默認(rèn)為0(即沒有小數(shù)位).
精度和小數(shù)位不會(huì)影響數(shù)據(jù)如何存儲(chǔ),只會(huì)影響允許哪些數(shù)值及數(shù)值如何舍入。
1.新建一個(gè)表
SQL> create table test_number(col_number number(6,2));
Table created
2.插入一些不同的數(shù)據(jù)
SQL> insert into test_number values(-1);
1 row inserted
SQL> insert into test_number values(0);
1 row inserted
SQL> insert into test_number values(1);
1 row inserted
SQL> insert into test_number values(2);
1 row inserted
SQL> insert into test_number values(11.00);
1 row inserted
SQL> insert into test_number values(11.11);
1 row inserted
SQL> insert into test_number values(1234.12);
1 row inserted
SQL> insert into test_number values(-0.1);
1 row inserted
SQL> insert into test_number values(-11.11);
1 row inserted
SQL> insert into test_number values(-1234.12);
1 row inserted
SQL> commit;
Commit complete
3.查看結(jié)果
SQL> select * from test_number;
COL_NUMBER
----------
???? -1.00
????? 0.00
????? 1.00
????? 2.00
???? 11.00
???? 11.11
?? 1234.12
???? -0.10
??? -11.11
? -1234.12
10 rows selected
5. 查看存儲(chǔ)結(jié)構(gòu)
SQL> select col_number, dump(col_number) from test_number;
COL_NUMBER DUMP(COL_NUMBER)
---------- --------------------------------------------------------------------------------
???? -1.00 Typ=2 Len=3: 62,100,102
????? 0.00 Typ=2 Len=1: 128
????? 1.00 Typ=2 Len=2: 193,2
????? 2.00 Typ=2 Len=2: 193,3
???? 11.00 Typ=2 Len=2: 193,12
???? 11.11 Typ=2 Len=3: 193,12,12
?? 1234.12 Typ=2 Len=4: 194,13,35,13
???? -0.10 Typ=2 Len=3: 63,91,102
??? -11.11 Typ=2 Len=4: 62,90,90,102
? -1234.12 Typ=2 Len=5: 61,89,67,89,102
10 rows selected
由此可見:
Number類型的內(nèi)部編碼為:2
根據(jù)每一行的len值可以看出,number是一個(gè)變長(zhǎng)類型。不同的數(shù)值占用不同的空間。
如果指定了精度,顯示結(jié)果與精度相關(guān)。
就像我插入語句寫為
insert into test_number values(0);
但是顯示結(jié)果為:0.00
如果數(shù)值是負(fù)數(shù),在最后一位上填充一個(gè)補(bǔ)碼102.即表示該數(shù)值為負(fù)數(shù)。
0是一個(gè)特殊的值,它在oracle中存儲(chǔ)為128.
第一位為標(biāo)志位。以128為比較。如果數(shù)值大于128,則它大于0。如果小于128小于0。
-1的內(nèi)部存儲(chǔ)為:
-1.00 Typ=2 Len=3: 62,100,102
最后一位是102,是一個(gè)負(fù)數(shù)。
第一位小于128,所以小于10.
除了第一位標(biāo)志位外,其它的都是數(shù)值為了。
如果該值是一個(gè)正數(shù)。每一位的存儲(chǔ)值減1為每一位的實(shí)際值。
1.0的存儲(chǔ)結(jié)構(gòu)為:
1.00 typ=2 Len=2: 193,2
實(shí)值上1.00的存儲(chǔ)結(jié)果與1相同。
第一位193為標(biāo)志位,大于128,大于0.
第二位為數(shù)值為,因?yàn)槭钦龜?shù),實(shí)際值為存儲(chǔ)值減1。2-1 = 1。
如是該值是一個(gè)負(fù)數(shù),每一位的實(shí)際值為101 減去存儲(chǔ)的值。
-1.00的存儲(chǔ)結(jié)構(gòu)為:
-1.00 Typ=2 Len=3: 62,100,102
最后一位102為補(bǔ)位。
第一位62為標(biāo)志位,小于128。實(shí)際值小于0.
第二位為數(shù)值為,因?yàn)槭秦?fù)數(shù)。實(shí)際值為:101 – 100? =1.
§2.2 小數(shù)位在哪里?
從上面的存儲(chǔ)結(jié)果看,對(duì)小數(shù)存儲(chǔ)時(shí),它并沒有一個(gè)小數(shù)的標(biāo)志位。但是它實(shí)際上是由第一位標(biāo)志位,和數(shù)值位(第二位)來決定的。
當(dāng)存儲(chǔ)的數(shù)是一個(gè)正數(shù),該數(shù)值的前幾位為:第一位 * power(100 , (標(biāo)志位 - 193));
當(dāng)存儲(chǔ)的數(shù)是一個(gè)負(fù)數(shù),該數(shù)值的前幾位為:第一位 * power(100,(62 – 標(biāo)志位));
11.11的存儲(chǔ)結(jié)果為:
11.11 Typ=2 Len=3: 193,12,12
第一位數(shù)值位為:12 實(shí)際數(shù)值為11
標(biāo)志位為:193
12 * power(100, (193- 193);
?? 100的零次方為1.
12 乘1 等于12.
所以這個(gè)數(shù)的前幾位為:12。從這后面就是小數(shù)了。
1234.12的存儲(chǔ)結(jié)構(gòu)為:
1234.12 Typ=2 Len=4: 194,13,35,13
第一位數(shù)值位為:13,實(shí)際值為12
標(biāo)志位為:193
13 * power(100,(194-193)) = 1300
所以前四位為整數(shù)位,后面的為小數(shù)位。
-0.10的存儲(chǔ)結(jié)構(gòu)為:
-0.10 Typ=2 Len=3: 63,91,102
標(biāo)志位為:63
第一位數(shù)值為:91 ,實(shí)際值為:10
91 * (100,(62-63)) =-9100.
所以小數(shù)位在91之前。
-1234.12的存儲(chǔ)結(jié)構(gòu)為:
-1234.12 Typ=2 Len=5: 61,89,67,89,102
標(biāo)志位為:61
第一位數(shù)值為:89
89*(100,(62-61)) =8900
所以小數(shù)位在67之后。
§2.3 number的精度和小數(shù)位
Number類型的精度最多可是38位。小數(shù)位-84--127位。
SQL> create table test_number1(col_number number(39));
create table test_number1(col_number number(39))
ORA-01727: numeric precision specifier is out of range (1 to 38)
指定小數(shù)位時(shí),精度只能是1-38。不能是0
SQL> create table test_number1(col_number number(0,127));
create table test_number1(col_number number(0,127))
ORA-01727: numeric precision specifier is out of range (1 to 38)
SQL> create table test_number1(col_number number(1,128));
create table test_number1(col_number number(1,128))
ORA-01728: numeric scale specifier is out of range (-84 to 127)
精度與小數(shù)位的關(guān)系。精度并不是小數(shù)位加整數(shù)位之和。
我們先看看小數(shù)位為0的情況。
SQL> create table test_number1(col_char varchar2(200), col_num number(10));
Table created
Number(10).只定義了精度,小數(shù)位為0.
看看它可以存放的數(shù)據(jù)。
SQL> insert into test_number1 values('9999999999',9999999999);
1 row inserted
插入了10個(gè)9,沒有問題,再插入多一位看看
SQL> insert into test_number1 values('99999999991',99999999991);
insert into test_number1 values('99999999991',99999999991)
ORA-01438: value larger than specified precision allowed for this column
報(bào)錯(cuò)了,精度不夠。
再看看能不能再插入小數(shù)?
SQL> insert into test_number1 values('0.9',0.9);
1 row inserted
SQL> select * from test_number1;
Col_char COL_NUM
-------------------- --------------
9999999999 9999999999
0.9 ???????????? 1
注意插入數(shù)值0.9后,存儲(chǔ)為1.這就是小數(shù)位的作用。在哪里進(jìn)行舍入。
帶小數(shù)位和精度的情況。
SQL> create table test_number2(col_char varchar(20),col_num number(1,3));
Table created
精度是1,小數(shù)位是3.
可見,精度不是小數(shù)位加整數(shù)位了。但是精度和小數(shù)位倒底什么關(guān)系呢?
SQL> insert into test_number2 values('0.111',0.111);
insert into test_number2 values('0.111',0.111)
ORA-01438: value larger than specified precision allowed for this column
插入3位小數(shù),0.111竟然報(bào)錯(cuò)了,說精度不夠。
SQL> insert into test_number2 values('0.001',0.001);
1 row inserted
插入0.001時(shí),成功了。
SQL> insert into test_number2 values('0.001',0.0015);
1 row inserted
插入0.0015也成功了。
看看插入的值。
SQL> select * from test_number2;
COL_CHAR???????????? COL_NUM
-------------------- -------
0.001????????????????? 0.001
0.0015???????????????? 0.002
需要注意的是0.0015被舍入為0.002
精度大于小數(shù)位
SQL> create table test_number3 (col_char varchar(20), col_number number(5,3));
Table created
SQL> insert into test_number3 values('99.899',99.899);
1 row inserted
SQL> insert into test_number3 values('99.999',99.999);
1 row inserted
SQL> insert into test_number3 values('99.9999',99.9999);
insert into test_number3 values('99.9999',99.9999)
ORA-01438: value larger than specified precision allowed for this column
注意,當(dāng)插入99.9999時(shí),系統(tǒng)報(bào)錯(cuò)。因?yàn)樾?shù)位為3位。第四位小數(shù)位是9,于是往前入。最終變成100.000.就已經(jīng)超過了精度。
Number(5,3)可存儲(chǔ)的數(shù)值最大為99.999.
現(xiàn)在終于有點(diǎn)明白小數(shù)位與精度的關(guān)系了。
number(38,127)
可以存儲(chǔ)的最大小數(shù)為:127位小數(shù),最后38為9.
即:0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000099999999999999999999999999999999999999
小數(shù)位為負(fù)數(shù)。
我們從前面知道,小數(shù)位的取值為-48 ~127
為什么小數(shù)位會(huì)為負(fù)數(shù)?這有點(diǎn)怪異了。像上面的number(5,3)將值舍入為最接近0.001
Number(5,-3)就是將值舍入為最接近的1000
SQL> create table test_number5 (col_char varchar(20), col_num number(5,-3));
Table created
插入值10999
SQL> insert into test_number5 values('10999',10999);
1 row inserted
查看一下結(jié)果
SQL> select * from test_number5;
COL_CHAR???????????? COL_NUM
-------------------- -------
10999????????????????? 11000
存儲(chǔ)的結(jié)果為:11000
當(dāng)小數(shù)部分為負(fù)數(shù)時(shí),是對(duì)小數(shù)部分進(jìn)行舍入。
那么精度在這時(shí)起到什么作用呢?與小數(shù)位又有什么關(guān)系?
SQL> insert into test_number5 values('111111111',111111111);
insert into test_number5 values('111111111',111111111)
ORA-01438: value larger than specified precision allowed for this column
插入9個(gè)1時(shí),報(bào)錯(cuò)精度不夠。
SQL> insert into test_number5 values('11111111',11111111);
1 row inserted
插入8個(gè)1時(shí),正確插入。
我們看看它的結(jié)果,看它是怎么舍入的。
SQL> select * from test_number5;
COL_CHAR???????????? COL_NUM
-------------------- -------
11111111???????????? 11111000
結(jié)果是1111100而不是1111100
無限接近1000,就是從百位開始進(jìn)行四舍五入,后面的值全部為0。
所以看出number(5,-3)可存儲(chǔ)的最大值為:99999000
SQL> insert into test_number5 values('99999499.999999',99999499.999999);
1 row inserted
SQL> select * from test_number5;
COL_CHAR???????????? COL_NUM
-------------------- -------
99999999???????????? 99999000
99999499.999999????? 99999000
現(xiàn)在應(yīng)該明白了精度和小數(shù)位的關(guān)系了吧。
小數(shù)位告訴系統(tǒng)保留多少位小數(shù),從哪里開始舍入。
精度舍入后,從舍入的位置開始,數(shù)值中允許有多少位。
§2.4? binary_float 和binary_double
這兩種類型是oracle 10g新引進(jìn)的數(shù)值類型。在oracle 10g之前是沒有這兩種類型的。
Number類型是由oracle軟件支持的類型。而浮點(diǎn)數(shù)用于近似數(shù)值。但是它浮點(diǎn)數(shù)允許由在硬盤上(CPU,芯片)上執(zhí)行運(yùn)行。而不是在oracel進(jìn)程中運(yùn)算。如果希望在一個(gè)科學(xué)計(jì)算中執(zhí)行實(shí)數(shù)處理,依賴于硬件的算術(shù)運(yùn)算速度要快得多。但是它的精度卻很小。如果希望用來存儲(chǔ)金融數(shù)值,則必須用number.
BINARY_FLOAT是一種IEEE固有的單精度浮點(diǎn)數(shù)。可存儲(chǔ)6位精度,取值范圍在~±1038.25的數(shù)值。
BINARY_DOUBLE是一種IEEE固有的雙精度浮點(diǎn)數(shù)。可存儲(chǔ)12位精度。取值范圍在~±10308.25的數(shù)值
SQL> create table test_floatdouble(col_number number, col_float binary_float, col_double binary_double);
Table created
SQL> insert into test_floatdouble values(9876543210.0123456789,9876543210.0123456789,9876543210.0123456789);
1 row inserted
2 SQL> select to_char(col_number), to_char(col_float), to_char(col_double) from test_floatdouble;
3
4 TO_CHAR(COL_NUMBER)????????????????????? TO_CHAR(COL_FLOAT)?????????????????????? TO_CHAR(COL_DOUBLE)
5 ---------------------------------------- ---------------------------------------- ----------------------------------------
6 9876543210.0123456789??????????????????? 9.87654349E+009????????????????????????? 9.8765432100123463E+009
由此可見,binary_float無法表示這個(gè)數(shù)。Binary_float和binary_double無法用于對(duì)精度要求高的數(shù)據(jù)。
SQL> select dump(col_float)from test_floatdouble;
DUMP(COL_FLOAT)
--------------------------------------------------------------------------------
Typ=100 Len=4: 208,19,44,6
BINARY_FLOAT 類型編碼為100
Len=4 占用4個(gè)字節(jié)。它是采用固定字節(jié)進(jìn)行存儲(chǔ)的。
SQL> select dump(col_double)from test_floatdouble;
DUMP(COL_DOUBLE)
--------------------------------------------------------------------------------
Typ=101 Len=8: 194,2,101,128,183,80,25,73
BINARY_DOUBLE 類型編碼為101
Leng= 8 占用8個(gè)字節(jié)。也是采用固定字節(jié)進(jìn)行存儲(chǔ)。
注意:number 類型使用的CPU時(shí)間是浮點(diǎn)數(shù)類型的50倍。浮點(diǎn)數(shù)是數(shù)值的一個(gè)近似值,精度在6-12位之間。從Number類型得到的結(jié)果要比從浮點(diǎn)數(shù)得到的結(jié)果更精確。但在對(duì)科學(xué)數(shù)據(jù)進(jìn)行數(shù)據(jù)挖掘和進(jìn)行復(fù)雜數(shù)值分析時(shí),精度的損失是可以接受的,還會(huì)帶來顯著的性能提升。
這時(shí)需要使用內(nèi)置CAST函數(shù),對(duì)NUMBER類型執(zhí)行一種實(shí)時(shí)的轉(zhuǎn)換,在執(zhí)行復(fù)雜數(shù)學(xué)運(yùn)算之前先將其轉(zhuǎn)換為一種浮點(diǎn)數(shù)類型。CPU使用時(shí)間就與固有浮點(diǎn)類型使用的CPU時(shí)間非常接近了。
Select ln(cast(number_col as binary_double)) from test_number.
§2.5 Oracle在語法上還支持的數(shù)值數(shù)據(jù)類型
NUMERIC(p,s):完全映射到NUMBER(p,s)。如果p未指定,則默認(rèn)為38.
DECIMAL(p,s)或DEC(p,s):同NUMERIC(p,s).
INTEGER或int:完全映射至NUMBER(38)
SMALLINT:完全映射至NUMBER(38)
FLOAT(b):映射至NUMBER
DOUBLE PRECISION:映射到NUMBER
REAL:映射到NUMBER.
轉(zhuǎn)載于:https://www.cnblogs.com/linsond/archive/2010/06/30/1767965.html
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的转--Oracle数据类型及存储方式【C】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Alpha通道
- 下一篇: Silverlight4.0(9) 之