?
本文檔使用 php中文網(wǎng)手冊(cè) 發(fā)布
數(shù)值類型由2,4或8字節(jié)的整數(shù)以及4或8字節(jié)的浮點(diǎn)數(shù)和可選精度的小數(shù)組成。 Table 8-2列出了所有可用類型。
Table 8-2. 數(shù)值類型
名字 | 存儲(chǔ)空間 | 描述 | 范圍 |
---|---|---|---|
smallint | 2字節(jié) | 小范圍整數(shù) | -32768到+32768 |
integer | 4字節(jié) | 常用的整數(shù) | -2147483648到+2147483647 |
bigint | 8字節(jié) | 大范圍的整數(shù) | -9223372036854775808到9223372036854775807 |
decimal | 變長 | 用戶聲明精度,精確 | 無限制 |
numeric | 變長 | 用戶聲明精度,精確 | 無限制 |
real | 4字節(jié) | 變精度,不精確 | 6位十進(jìn)制數(shù)字精度 |
double precision | 8字節(jié) | 變精度,不精確 | 15位十進(jìn)制數(shù)字精度 |
serial | 4字節(jié) | 自增整數(shù) | 1到2147483647 |
bigserial | 8字節(jié) | 大范圍的自增整數(shù) | 1到9223372036854775807 |
數(shù)值類型常量的語法在Section 4.1.2里描述。 數(shù)值類型對(duì)應(yīng)有一套完整的數(shù)學(xué)操作符和函數(shù)。 相關(guān)信息請(qǐng)參考Chapter 9。 下面的幾節(jié)詳細(xì)描述這些類型。
smallint,integer,bigint類型存儲(chǔ)各種范圍的全部是數(shù)字的數(shù), 也就是沒有小數(shù)部分的數(shù)字。試圖存儲(chǔ)超出范圍以外的數(shù)值將導(dǎo)致一個(gè)錯(cuò)誤。
常用的類型是integer,因?yàn)樗峁┝嗽诜秶?、存?chǔ)空間、性能之間的最佳平衡。 一般只有在磁盤空間緊張的時(shí)候才使用smallint。 而只有在integer的范圍不夠的時(shí)候才使用bigint,因?yàn)榍罢呓^對(duì)快得多。
在很小的操作系統(tǒng)上,bigint類型可能無法正常工作,因?yàn)樗蕾嚲幾g器對(duì)八字節(jié)整數(shù)的支持。在那些沒有八字節(jié)整數(shù)支持的機(jī)器上, bigint的作用和integer一樣(但是仍然占據(jù)八字節(jié)存儲(chǔ))。 不過,我們目前還沒聽說過有這樣的平臺(tái)。
SQL只聲明了整數(shù)類型integer(或int)和smallint,bigint。 類型別名int2,int4,int8都是擴(kuò)展,并且也在許多其它SQL數(shù)據(jù)庫系統(tǒng)中使用。
numeric類型可以存儲(chǔ)最多1000位精度的數(shù)字并且準(zhǔn)確地進(jìn)行計(jì)算。 我們特別建議將它用于貨幣金額和其它要求精確計(jì)算的場合。 不過,numeric類型上的算術(shù)運(yùn)算比整數(shù)類型或者我們下一節(jié)描述的浮點(diǎn)數(shù)類型要慢很多。
我們使用下述術(shù)語: 一個(gè)numeric類型的標(biāo)度(scale)是小數(shù)部分的位數(shù),精度(precision)是全部數(shù)據(jù)位的數(shù)目, 也就是小數(shù)點(diǎn)兩邊的位數(shù)總和。因此數(shù)字23.5141的精度為6而標(biāo)度為4。你可以認(rèn)為整數(shù)的標(biāo)度為零。
numeric字段的最大精度和最大標(biāo)度都是可以配置的。 要聲明一個(gè)字段的類型為numeric,你可以用下面的語法:
NUMERIC(precision, scale)
精度必須為正數(shù),標(biāo)度可以為零或者正數(shù)。另外,
NUMERIC(precision)
選擇了標(biāo)度為0.具體說明:
NUMERIC
則創(chuàng)建一個(gè)可以存儲(chǔ)一個(gè)直到實(shí)現(xiàn)精度上限的任意精度和標(biāo)度的數(shù)值, 一個(gè)這樣類型的字段將不會(huì)把輸入數(shù)值轉(zhuǎn)化成任何特定的標(biāo)度, 而帶有標(biāo)度聲明的numeric字段將把輸入值轉(zhuǎn)化為該標(biāo)度。 SQL標(biāo)準(zhǔn)要求缺省的標(biāo)度是 0(也就是轉(zhuǎn)化成整數(shù)精度)。 我們覺得這樣做有點(diǎn)沒用。如果你關(guān)心移植性,那你最好總是明確聲明精度和標(biāo)度。
如果一個(gè)要存儲(chǔ)的數(shù)值的標(biāo)度比字段聲明的標(biāo)度高, 那么系統(tǒng)將嘗試圓整(四舍五入)該數(shù)值到指定的小數(shù)位。 然后,如果小數(shù)點(diǎn)左邊的數(shù)據(jù)位數(shù)超過了聲明的精度減去聲明的標(biāo)度, 那么將拋出一個(gè)錯(cuò)誤。
numeric類型的數(shù)據(jù)值在物理上是不帶任何前導(dǎo)或者后綴零的形式存儲(chǔ)的。 因此,字段上聲明的精度和標(biāo)度都是最大值,而不是固定分配的。 在這個(gè)方面,numeric類型更類似于varchar(n) 而不是char(n)。實(shí)際存儲(chǔ)是每四個(gè)十進(jìn)制位兩個(gè)字節(jié), 然后在整個(gè)數(shù)據(jù)上加上八個(gè)字節(jié)的額外開銷。
除了普通的數(shù)字值之外,numeric類型允許用特殊值NaN 表示"不是一個(gè)數(shù)字"。任何在NaN上面的操作都生成另外一個(gè)NaN。 如果在 SQL 命令里把這些值當(dāng)作一個(gè)常量寫,你必須在其周圍放上單引號(hào), 比如UPDATE table SET x = 'NaN'。在輸入時(shí),字符串NaN是大小寫無關(guān)的。
Note: 在大多數(shù)"not-a-number"概念中,不認(rèn)為NaN等于其他數(shù)值類型(包括NaN)。 為了能夠存儲(chǔ)numeric類型的值,并且使用Tree索引, PostgreSQL認(rèn)為NaN相等,并且大于所有非NaN值。
類型decimal和numeric是等效的。 兩種類型都是SQL標(biāo)準(zhǔn)。
數(shù)據(jù)類型real和double precision是不精確的、變精度的數(shù)字類型。 實(shí)際上,這些類型是IEEE754標(biāo)準(zhǔn)二進(jìn)制浮點(diǎn)數(shù)算術(shù)(分別對(duì)應(yīng)單和雙精度)的一般實(shí)現(xiàn), 外加下層處理器、操作系統(tǒng)和編譯器對(duì)它的支持。
不精確意味著一些數(shù)值不能精確地轉(zhuǎn)換成內(nèi)部格式并且是以近似值存儲(chǔ)的, 因此存儲(chǔ)后再把數(shù)據(jù)打印出來可能有一些差異。 處理這些錯(cuò)誤以及這些錯(cuò)誤是如何在計(jì)算中傳播的屬于數(shù)學(xué)和計(jì)算機(jī)科學(xué)的一個(gè)完整的分支, 我們不會(huì)在這里進(jìn)一步討論它,這里的討論僅限于如下幾點(diǎn):
如果你要求精確的計(jì)算(比如計(jì)算貨幣金額),應(yīng)使用numeric類型。
如果你想用這些類型做任何重要的復(fù)雜計(jì)算, 尤其是那些你對(duì)范圍情況(無窮/下溢)嚴(yán)重依賴的事情,那你應(yīng)該仔細(xì)評(píng)詁你的實(shí)現(xiàn)。
拿兩個(gè)浮點(diǎn)數(shù)值進(jìn)行相等性比較可能不像你想像那樣運(yùn)轉(zhuǎn)。
在大多數(shù)平臺(tái)上,real類型的范圍是至少1E-37到1E+37, 精度至少是6位小數(shù)。double precision的范圍通常是1E-307到1E+308, 精度是至少15位數(shù)字。太大或者太小的數(shù)值都會(huì)導(dǎo)致錯(cuò)誤。 如果輸入數(shù)據(jù)的精度太高,那么將會(huì)發(fā)生園整。太接近零的數(shù)字, 如果無法與零值的表現(xiàn)形式相區(qū)分就會(huì)產(chǎn)生下溢錯(cuò)誤。
除了普通的數(shù)字值之外,浮點(diǎn)類型還有幾個(gè)特殊值:
Infinity
-Infinity
NaN
Note: IEEE754聲明NaN不應(yīng)該等于任何其他浮點(diǎn)值(包括NaN)。 為了能存儲(chǔ)浮點(diǎn)值,并且使用Tree索引,PostgreSQL認(rèn)為NaN相等,并且大于所有非NaN值。
PostgreSQL還支持SQL標(biāo)準(zhǔn)表示法float和float(p)用于聲明非精確的數(shù)值類型。 其中的p聲明以二進(jìn)制位表示的最低可接受二進(jìn)制精度。 在選取real類型的時(shí)候, PostgreSQL接受float(1)到float(24), 在選取double precision的時(shí)候, 接受float(25) 到float(53)。 在允許范圍之外的p值將導(dǎo)致一個(gè)錯(cuò)誤。 沒有聲明精度的float將被當(dāng)作double precision。
Note: PostgreSQL7.4以前, 在float(p)里面 的精度會(huì)被當(dāng)作是這么多位小數(shù)的十進(jìn)制位。 到7.4已經(jīng)被修改成與SQL標(biāo)準(zhǔn)匹配,標(biāo)準(zhǔn)聲明這個(gè)精度是以二進(jìn)制位度量的。 假設(shè)real和double precision分別有24和53個(gè)二進(jìn)制位的位數(shù)對(duì) IEEE 標(biāo)準(zhǔn)的浮點(diǎn)實(shí)現(xiàn)來說是正確的。在非IEEE平臺(tái)上, 這個(gè)數(shù)值可能略有偏差,但是為了簡化,我們?cè)谒衅脚_(tái)上都用了同樣的p值范圍。
serial和bigserial類型不是真正的類型, 只是為在表中設(shè)置唯一標(biāo)識(shí)做的概念上的便利。 類似其它一些數(shù)據(jù)庫中的AUTO_INCREMENT屬性。 在目前的實(shí)現(xiàn)中,下面一個(gè)語句:
CREATE TABLE tablename ( colname SERIAL );
等價(jià)于聲明下面幾個(gè)語句:
CREATE SEQUENCE tablename_colname_seq; CREATE TABLE tablename ( colname integer NOT NULL DEFAULT nextval('tablename_colname_seq') ); ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
因此,我們就創(chuàng)建了一個(gè)整數(shù)字段并且把它的缺省數(shù)值安排為從一個(gè)序列發(fā)生器讀取。 應(yīng)用了一個(gè)NOT NULL約束以確保NULL不會(huì)被插入。 在大多數(shù)情況下你可能還希望附加一個(gè)UNIQUE或PRIMARY KEY約束避免意外地插入重復(fù)的數(shù)值, 但這個(gè)不是自動(dòng)的。最后,將序列發(fā)生器"從屬于"那個(gè)字段, 這樣當(dāng)該字段或表被刪除的時(shí)候也一并刪除它。
Note: PostgreSQL7.3以前, serial隱含UNIQUE。 但現(xiàn)在不再如此。如果你希望一個(gè)序列字段有一個(gè)唯一約束或者一個(gè)主鍵, 那么你現(xiàn)在必須聲明,就像其它數(shù)據(jù)類型一樣。
要在serial字段中插入序列中的下一個(gè)數(shù)值, 主要是要注意serial字段應(yīng)該賦予缺省值。 我們可以通過在INSERT語句中把該字段排除在字段列表之外來實(shí)現(xiàn), 也可以通過使用DEFAULT關(guān)鍵字來實(shí)現(xiàn)。
類型名serial和serial4是等效的: 兩者都創(chuàng)建integer字段。 類型名bigserial和serial8也一樣, 只不過它創(chuàng)建一個(gè)bigint字段。 如果你預(yù)計(jì)在表的生存期中使用的標(biāo)識(shí)數(shù)目可能超過231個(gè), 那么你應(yīng)該使用bigserial。
一個(gè)serial類型創(chuàng)建的序列在所屬的字段被刪除的時(shí)候自動(dòng)刪除。 你可以只刪除序列而不刪除字段,不過這將刪除該字段的缺省值表達(dá)式。