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