表8-2. 數值類型
名字
存儲空間
描述
範圍
smallint
2 字節
小範圍整數
-32768 到 +32767
integer
4 字節
常用的整數
-2147483648 到 +2147483647
bigint
8 字節
大範圍的整數
-9223372036854775808 到 9223372036854775807
decimal
變長
用戶聲明精度,精確
無限制
numeric
變長
用戶聲明精度,精確
無限制
real
4 字節
變精度,不精確
6 位十進制數字精度
double precision
8 字節
變精度,不精確
15 位十進制數字精度
serial
4 字節
自增整數
1 到 2147483647
bigserial
8 字節
大範圍的自增整數
1 到 9223372036854775807
numeric 類型可以存儲最多 1000 位精度的數字並且準確地進行計算。我們特別建議將它用於貨幣金額和其它要求精確計算的場合。不過,numeric 類型上的算術運算比整數類型或者我們下一節描述的浮點數類型要慢很多。
在隨後的內容裏,我們使用下述術語:一個 numeric 類型的標度(scale)是小數部分的位數,精度(precision)是全部數據位的數目,也就是小數點兩邊的位數總和。因此數字 23.5141 的精度爲 6 而標度爲 4 。你可以認爲整數的標度爲零。
numeric 字段的最大精度和最大標度都是可以配置的。要聲明一個字段的類型爲 numeric ,你可以用下面的語法:
NUMERIC(precision, scale)
精度必須爲正數,標度可以爲零或者正數。另外,
NUMERIC(precision)
選擇了標度爲 0 。不帶任何精度與標度的聲明
NUMERIC
則創建一個可以存儲一個直到實現精度上限的任意精度和標度的數值,一個這樣類型的字段將不會把輸入數值轉化成任何特定的標度,而帶有標度聲明的 numeric 字段將把輸入值轉化爲該標度。SQL 標準要求缺省的標度是 0(也就是轉化成整數精度)。我們覺得這樣做有點沒用。如果你關心移植性,那你最好總是明確聲明精度和標度。
如果一個要存儲的數值的標度比字段聲明的標度高,那麼系統將嘗試圓整(四捨五入)該數值到指定的小數位。然後,如果小數點左邊的數據位數超過了聲明的精度減去聲明的標度,那麼將拋出一個錯誤。
numeric 類型的數據值在物理上是不帶任何前導或者後綴零的形式存儲的。因此,字段上聲明的精度和標度都是最大值,而不是固定分配的。在這個方面,numeric 類型更類似於 varchar(n) 而不是 char(n) 。實際存儲是每四個十進制位兩個字節,然後在整個數據上加上八個字節的額外開銷。
除了普通的數字值之外,numeric 類型允許用特殊值 NaN 表示"不是一個數字"。任何在 NaN 上面的操作都生成另外一個 NaN 。如果在 SQL 命令裏把這些值當作一個常量寫,你必須在其周圍放上單引號,比如 UPDATE table SET x = 'NaN' 。在輸入時,字符串 NaN 是大小寫無關的。
類型 decimal 和 numeric 是等效的。兩種類型都是 SQL 標準。
表8-4. 字符類型
名字
描述
character varying(n), varchar(n)
變長,有長度限制
character(n), char(n)
定長,不足補空白
text
變長,無長度限制
SQL 定義了兩種基本的字符類型:character varying(n) 和 character(n) ,這裏的 n 是一個正整數。兩種類型都可以存儲最多 n 個字符的字符串。試圖存儲更長的字符串到這些類型的字段裏會產生一個錯誤,除非超出長度的字符都是空白,這種情況下該字符串將被截斷爲最大長度。這個看上去有點怪異的例外是 SQL 標準要求的。如果要存儲的字符串比聲明的長度短,類型爲 character 的數值將會用空白填滿;而類型爲 character varying 的數值將只是存儲短些的字符串。
如果我們明確地把一個數值轉換成 character varying(n) 或 character(n) ,那麼超長的數值將被截斷成 n 個字符,且不會拋出錯誤。這也是 SQL 標準的要求。
varchar(n) 和 char(n) 分別是 character varying(n) 和 character(n)的別名,沒有聲明長度的 character 等於 character(1) ;如果不帶長度說明詞使用 character varying,那麼該類型接受任何長度的字符串。後者是 PostgreSQL 的擴展。
另外,PostgreSQL 提供 text 類型,它可以存儲任何長度的字符串。儘管類型 text 不是 SQL 標準,但是許多其它 SQL 數據庫系統也有它。
character 類型的數值物理上都用空白填充到指定的長度 n 並且以這種方式存儲和顯示。不過,填充的空白在是無語意的。在比較兩個 character 值的時候,填充的空白都不會被關注,在轉換成其它字符串類型的時候,character 值裏面的空白會被刪除。請注意,在 character varying 和 text 數值裏,結尾的空白是有語意的。
這些類型的存儲需求是 4 字節加上實際的字符串,如果是 character 的話再加上填充的字節。長的字符串將會自動被系統壓縮,因此在磁盤上的物理需求可能會更少些。長的數值也會存儲在後臺表裏面,這樣它們就不會干擾對短字段值的快速訪問。不管怎樣,允許存儲的最長字符串大概是 1GB 。允許在數據類型聲明中出現的 n 的最大值比這還小。修改這個行爲沒有什麼意義,因爲在多字節編碼下字符和字節的數目可能差別很大。如果你想存儲沒有特定上限的長字符串,那麼使用 text 或沒有長度聲明詞的 character varying ,而不要選擇一個任意長度限制。
【提示】這三種類型之間沒有性能差別,只不過是在使用 character 的時候增加了存儲尺寸。雖然在某些其它的數據庫系統裏,character(n) 有一定的性能優勢,但在 PostgreSQL 裏沒有。在大多數情況下,應該使用 text 或 character varying 。
表8-9. 日期/時間類型
名字
存儲空間
描述
最低值
最高值
分辨率
timestamp [ (p) ] [ without time zone ]
8 字節
日期和時間
4713 BC
5874897 AD
1 毫秒 / 14 位
timestamp [ (p) ] with time zone
8 字節
日期和時間,帶時區
4713 BC
5874897 AD
1 毫秒 / 14 位
interval [ (p) ]
12 字節
時間間隔
-178000000 年
178000000 年
1 毫秒 / 14 位
date
4 字節
只用於日期
4713 BC
5874897 AD
1 天
time [ (p) ] [ without time zone ]
8 字節
只用於一日內時間
00:00:00
24:00:00
1 毫秒 / 14 位
time [ (p) ] with time zone
12 字節
只用於一日內時間,帶時區
00:00:00+1459
24:00:00-1459
1 毫秒 / 14 位